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.
}
使用带有 .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.
}