CSVHelper-使用两个映射类,并根据csv文件每一行的字段中的值选择映射

时间:2019-10-01 18:25:20

标签: c# csvhelper

使用CSVHelper .NET库和.NET Core 2.2来解析大型csv文件(超过一百万行)并将其写入SQL Server表中。

我有两个映射类:我们需要遍历每一行,并且如果该行的第一个值为1,则需要使用类映射1,如果值是2,则需要使用类映射2 。由于CSVHelper旨在批量进行此活动,因此在概念化如何使用if语句和for each循环来完成此任务方面遇到困难。

这是我到目前为止所拥有的:

SQL实体类

public class TaskEntity
{
    public int Id { get; set; }
    public string SqlTableColumn1 { get; set; }
    public string SqlTableColumn2 { get; set; }
}

CSVHelper映射类1

public sealed class TaskEntityMap1 : ClassMap<TaskEntity>
{
    public TaskEntityMap1()
    {
        Map(m => m.SqlTableColumn1).Name("CsvColumn1");
        Map(m => m.SqlTableColumn2).ConvertUsing(row => row.GetField<string>("CsvColumn2") + " " + row.GetField<string>("CsvColumn3"));
    }
}

CSVHelper映射类2

public sealed class TaskEntityMap2 : ClassMap<TaskEntity>
{
    public TaskEntityMap2()
    {
        Map(m => m.SqlTableColumn1).Name("CsvColumn4");
        Map(m => m.SqlTableColumn2).ConvertUsing(row => row.GetField<string>("CsvColumn5") + " " + row.GetField<string>("CsvColumn6"));
    }
}

Program.cs (这是我们之前收到的条件映射要求)

public static void Main(string[] args)
{
    using (var reader = new StreamReader(@"C:\Users\me\Documents\file.csv"))
    using (var csv = new CsvReader(reader))          
    {
        csv.Configuration.PrepareHeaderForMatch = (string header, int index) =>
            header.Replace(" ", "_").Replace("(", "").Replace(")", "").Replace(".", "");

        csv.Configuration.RegisterClassMap<TaskEntityMap>();

        var records = csv.GetRecords<TaskEntity>().ToList();
    }
}

如上面的Program.cs代码示例所示,该典型的易用方案似乎是CSVHelper设计的,我在概念上很难理解如何使用两个类映射以及如何遍历csv文件的每一行,然后根据给定行中一列中的值选择类映射。

1 个答案:

答案 0 :(得分:1)

当我最初听到您的要求时,我认为您只需要为每个文档检查一次ClassMap。现在听起来好像每行都会改变。不幸的是,我发现一旦您注册并开始使用ClassMap,它似乎就会被缓存,并且您无法将其切换到一半,因此我认为这两个ClassMaps不会起作用。我会给您几种解决方法,您可以让我知道其中一个是否满足您的要求。

public static void Main(string[] args)
{
    using (var reader = new StreamReader(@"C:\Users\me\Documents\file.csv"))
    using (var csv = new CsvReader(reader))          
    {
        csv.Configuration.PrepareHeaderForMatch = (string header, int index) =>
            header.Replace(" ", "_").Replace("(", "").Replace(")", "").Replace(".", "");

        csv.Configuration.RegisterClassMap<TaskEntityMap>();

        var records = csv.GetRecords<TaskEntity>().ToList();
    }
}

public sealed class TaskEntityMap : ClassMap<TaskEntity>
{
    public TaskEntityMap()
    {
        Map(m => m.SqlTableColumn1).ConvertUsing(row => row.GetField<int>(0) == 1 ? 
            row.GetField<string>("CsvColumn1") : 
            row.GetField<string>("CsvColumn4")
            );
        Map(m => m.SqlTableColumn2).ConvertUsing(row => row.GetField<int>(0) == 1 ? 
            row.GetField<string>("CsvColumn2") + " " + row.GetField<string>("CsvColumn3") :
            row.GetField<string>("CsvColumn5") + " " + row.GetField<string>("CsvColumn6")
            );
    }
}

另一种选择是手动构造TaskEntity对象。

public static void Main(string[] args)
{
    using (var reader = new StreamReader(@"C:\Users\me\Documents\file.csv"))
    using (var csv = new CsvReader(reader))          
    {
        csv.Configuration.PrepareHeaderForMatch = (string header, int index) =>
            header.Replace(" ", "_").Replace("(", "").Replace(")", "").Replace(".", "");

        var records = new List<TaskEntity>();

        csv.Read();
        csv.ReadHeader();

        while (csv.Read())
        {                    
            if (csv.GetField<int>(0) == 1)
            {
                var record = new TaskEntity
                {
                    SqlTableColumn1 = csv.GetField<string>("CsvColumn1"),
                    SqlTableColumn2 = csv.GetField<string>("CsvColumn2") + " " + csv.GetField<string>("CsvColumn3")
                };
                records.Add(record);
            }
            else
            {
                var record = new TaskEntity
                {
                    SqlTableColumn1 = csv.GetField<string>("CsvColumn4"),
                    SqlTableColumn2 = csv.GetField<string>("CsvColumn5") + " " + csv.GetField<string>("CsvColumn6")
                };
                records.Add(record);
            }                    
        }
    }  // Break here.
}