[英]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.