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

CSVHelper - using two mapping classes and choosing the mapping based on the value in a field of each row of the csv file

使用带有 .NET Core 2.2 的 CSVHelper .NET 库解析大型 csv 文件(超过 100 万行)并将其写入 SQL 服务器 table。

我有两个映射classes:我们需要遍历每一行,如果该行的第一个值是1,我们需要使用class映射1,如果值为 2,我们需要使用 class 映射 2。因为 CSVHelper 适合批量执行此 activity,所以我无法概念化如何使用 if 语句和 for each循环完成这个任务。

这是我目前拥有的:

SQL实体Class

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

CSVHelper 映射 Class 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 映射 Class 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 似乎专为之设计的典型易用性场景,我很难概念化如何使用两个 class 映射, 以及如何遍历 csv 文件的每一行并根据给定行中列中的值选择 class 映射。

当我最初听到您的要求时,我认为您只需要为每个文档检查一次 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.
}