ASP.NET 2.0 引入的 SqlBulkCopy 類,是 .NET 開發者進行高效率資料大量載入的利器。它繞過普通 INSERT 的解析、編譯、執行計畫產生等開銷,直接以資料流形式將 DataTable、DataReader、陣列批次寫入 SQL Server,效能較逐筆寫入提升 10 倍至 100 倍。本文系統梳理核心 API、關鍵屬性、實戰範本與避坑指南。
| 方法 | 適用場景 | 效能特徵 |
|---|---|---|
WriteToServer(DataReader) | 海量資料、單向流式讀取、記憶體敏感環境 | 最快,不佔用客戶端大量記憶體,流式傳輸 |
WriteToServer(DataTable) | 中等資料量、需在記憶體中轉換/清洗資料 | 需先載入完整 DataTable,記憶體壓力較大 |
WriteToServer(DataRow[]) | 批次更新、需篩選特定狀態列 | 靈活但需自行管理批次大小 |
BatchSize (預設 0 = 全部一次送)BulkCopyTimeout (預設 30 秒)ColumnMappingsNotifyAfter + SqlRowsCopied 事件DestinationTableNamedbo.TargetTable),避免解析歧義。using (var srcConn = new SqlConnection(srcConnStr))
using (var destConn = new SqlConnection(destConnStr))
{
srcConn.Open();
destConn.Open();
using (var cmd = new SqlCommand("SELECT Id, Name, Amount FROM SourceTable", srcConn))
using (var reader = cmd.ExecuteReader())
using (var bulk = new SqlBulkCopy(destConn))
{
bulk.DestinationTableName = "dbo.DestTable";
bulk.BatchSize = 2000;
bulk.BulkCopyTimeout = 1800;
bulk.NotifyAfter = 5000;
bulk.SqlRowsCopied += (s, e) =>
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 已寫入 {e.RowsCopied:N0} 筆");
// 明確欄位映射(來源序數 → 目標名稱)
bulk.ColumnMappings.Add("Id", "Id");
bulk.ColumnMappings.Add("Name", "FullName");
bulk.ColumnMappings.Add("Amount", "TotalAmount");
bulk.WriteToServer(reader);
}
}
AFTER INSERT Trigger、檢查 FK/CHECK。大量載入前建議 ALTER TABLE ... NOCHECK CONSTRAINT ALL / DISABLE TRIGGER ALL,完成後重啟並 CHECK CONSTRAINT ALL 驗證。SqlBulkCopyOptions.KeepIdentity 保留來源值。SqlBulkCopy 依賴 ADO.NET Type Mapper,特殊類型(sql_variant, UDT, XML Schema Collection)需預先在客戶端轉為支援類型。BatchSize=5000、DataReader 來源:約 45 秒完成(約 22 萬列/秒)INSERT ... VALUES 批次 1000:約 25 分鐘TABLOCK Hint (via SqlBulkCopyOptions.TableLock) 可再提升 20%~30%掌握 SqlBulkCopy,讓 .NET 應用在資料遷移、ETL、即時匯入等場景游刃有餘,告別「一條條 INSERT」的低效時代。