[英]how to import large CSV file to SQL server using .net core API
如何导入大型 CSV 文件到 SQL 服务器使用.Net Core API (C#)
我试过下面的代码,它适用于少量数据,但我如何导入大量数据(csv 文件中大约 1000000 条记录)成块。
public void LoadFile()
{
string filePath = @"F:\Test\Book1.csv";
using (var reader = new StreamReader(filePath))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var records = csv.GetRecords<SalesRecord>();
foreach (var record in records)
{
SalesRecord _salesRecord = new SalesRecord();
_salesRecord.Region = record.Region;
_salesRecord.Country = record.Country;
_salesRecord.ItemType = record.ItemType;
_salesRecord.SalesChannel = record.SalesChannel;
_salesRecord.OrderPriority = record.OrderPriority;
_salesRecord.OrderDate = record.OrderDate;
_salesRecord.OrderID = record.OrderID;
_salesRecord.ShipDate = record.ShipDate;
_salesRecord.UnitsSold = record.UnitsSold;
_salesRecord.UnitPrice = record.UnitPrice;
_salesRecord.UnitCost = record.UnitCost;
_salesRecord.TotalRevenue = record.TotalRevenue;
_salesRecord.TotalCost = record.TotalCost;
_salesRecord.TotalProfit = record.TotalProfit;
_context.SalesRecords.Add(_salesRecord);
}
_context.SaveChanges();
}
EF Core 或任何其他 ORM 均不适用于批量导入。 它们旨在给人一种使用内存中对象的印象。 在 ETL/批量导入作业中,除了行、字段、转换之外,没有任何对象可以开始。 为了扩展,ETL 作业应该加载比必要更多的数据。 ORM 的缓存、查询和映射功能在这种情况下只是开销,增加了很大的延迟。 管理事务和批量大小(ETL 中最重要的考虑因素之一)非常困难,只能间接配置。
从客户端导入数据的最快方法是使用SqlBulkCopy 。 此 class 使用与 BCP 或 BULK INSERT 相同的协议来以最少的日志记录插入数据——这意味着仅记录数据页,而不记录单个 INSERT。
SqlBulkCopy 只接受 DataTable 或 IDbDataReader。 幸运的是,CsvHelper 提供了一个CsvDataReader接口,因此可以将行从 CSV 直接复制到数据库:
using (var reader = new StreamReader("path\\to\\file.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
// Do any configuration to `CsvReader` before creating CsvDataReader.
using (var dr = new CsvDataReader(csv))
using (var con=new SqlConnection(connectionString))
using (var bcp=new SqlBulkCopy(con))
{
bcp.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns";
con.Open();
bcp.WriteToServer(reader);
}
}
这将按 position 匹配源列和目标列,并期望数据类型匹配。 这必须在 CsvReader 的配置中完成。
在大多数情况下,源和目标列名称必须通过ColumnMappings集合按 position 或名称进行映射:
bcp.ColumnMappings("SourceA","TargetA");
bcp.ColumnMappings("SourceB","TargetB");
通过将EnableStreaming设置为 false,可以将 SqlBulkCopy 配置为读取 stream 中的数据。 默认情况下,它将缓存 memory 中的所有行,然后再将它们发送到服务器。 批量大小可以通过BatchSize属性进行配置。
SqlBulkCopy 可以每批使用一个事务,也可以对整个操作使用一个事务。 批处理和事务交互的方式在事务和批量复制操作中有解释。
构造函数中的SqlBulkCopyOptions参数可用于指定与BULK INSERT
选项对应的其他重要设置,例如
导入任何 IEnumerable<>
SqlBulkCopy by using [FastMember's](https://github.com/mgravell/fast-member#ever-needed-an-idatareader)
ObjectReader` 包装器,任何IEnumerable<T>
集合都可以与 SqlBulkCopy 一起使用:
IEnumerable<SomeType> data = ...
using(var bcp = new SqlBulkCopy(connection))
using(var reader = ObjectReader.Create(data))
{
bcp.DestinationTableName = "SomeTable";
bcp.WriteToServer(reader);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.