簡體   English   中英

如何使用 .net 核心 API 將大型 CSV 文件導入到 SQL 服務器

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM