我目前的項目由3個標準層組成:數據,業務和演示。我想使用數據實體來滿足我所有的數據訪問需求。應用程序的部分功能將會需要將平面文件中的所有數據複製到數據庫中。該文件不是很大,所以我可以使用SqlBulkCopy。我發現了幾篇關於.NET中SqlBulkCopy類的使用的文章。但是,所有文章都使用數據表來回傳輸數據。SqlBulkCopy和實體框架
有沒有辦法與SqlBulkCopy一起使用數據實體還是必須使用DataTables?
我目前的項目由3個標準層組成:數據,業務和演示。我想使用數據實體來滿足我所有的數據訪問需求。應用程序的部分功能將會需要將平面文件中的所有數據複製到數據庫中。該文件不是很大,所以我可以使用SqlBulkCopy。我發現了幾篇關於.NET中SqlBulkCopy類的使用的文章。但是,所有文章都使用數據表來回傳輸數據。SqlBulkCopy和實體框架
有沒有辦法與SqlBulkCopy一起使用數據實體還是必須使用DataTables?
您可以將數據集視爲數據實體的序列化。不過,一般來說,我認爲SqlBulkCopy是一個table to table的表,因此對於datatables的原因。
SqlBulkCopy在調用WriteToServer方法時使用IDataReader,因此您應該能夠基於IEnumerable集合實現IDataReader。這將允許您接受實體集並使用您的IDataReader實現調用SqlBulkCopy。
您需要將實體轉換爲IDataReader或DataTable。
有一個小的輔助類,旨在協助有: http://archive.msdn.microsoft.com/LinqEntityDataReader/Release/ProjectReleases.aspx?ReleaseId=389
編輯:MSDN鏈接被打破,ALT副本可以在這裏找到: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs
然後你可以使用SqlBulkCopy的像這樣:
var sbCopy= new SqlBulkCopy(connectionString);
sbCopy.DestinationTableName = "TableName";
sbCopy.WriteToServer(entitiesList.AsDataReader());
我們嘗試並測試了幾種使用EF進行批量插入的方法,並最終使用表值參數獲取th e在各種行尺寸下的最佳性能。我沒有這些數字,但我知道Performance of bcp/BULK INSERT vs. Table-Valued Parameters是一個指導性因素。
我們最初使用SqlBulkCopy
加上一個適配器,該適配器需要一個IEnumerable<T>
並創建了一個IDataReader
。它還爲SqlBulkCopy生成了相關的元數據。這裏的優點是導入只是一個代碼。 @davehogan發佈的代碼被用作此的基礎。
表值參數需要存儲過程和數據庫中定義的表類型。如果您首先使用代碼,則可以執行SQL以創建這些作爲創建腳本的一部分。雖然這是更多的工作,但我們發現我們獲得了數據庫中行的更一致和更快的吞吐量。
此外,它是值得考慮的不是批量插入到您的主表。一旦數據被導入,我們使用一個臨時堆表併爲其添加一個聚集索引。然後我們在臨時表和主表之間執行MERGE
。這具有在插入並提高併發性時不鎖定主表索引的好處。我們傾向於使用此方法插入每個CPU插入2500行/秒。
讓我知道你是否想要更多的信息。
SqlBulkCopy是一種直接的,幾乎類似於字節陣列的行數據從客戶端傳輸到SQL Server。這是將數據導入SQL Server的最有效方式。
但是,它的性能在於真正的「批量」操作。數百或數千行不一定足夠高以證明其用途。數萬到數百萬行SqlBulkCopy的性能將真正發揮。最後,我們真正討論的是將數據發送到服務器。
將一組行集合到生產數據庫的表中還有其他重大挑戰。重新編排,重新排序(如果有聚集索引),外鍵驗證,所有這些東西都會增加插入時間,並且可能會對錶和索引進行鎖定。
此外,TVP數據寫入磁盤(作爲臨時表數據),然後可以放入您的表中。 SqlBulkCopy能夠直接在你的桌面上執行......在這種情況下,性能顯着加快,但是,必須平衡併發速度。
我認爲總體規則是,如果你有幾行處理,想想TVPs,並且如果你有成千上萬的行,可以考慮通過SqlBulkCopy儘可能快地到SQL Server。
以補充@DaveHogan答案,
現在有新的庫允許使用的數據實體,而不是數據表的實體框架執行批量插入(在引擎蓋下使用SqlBulkCopy的)。
免責聲明:我的項目Entity Framework Extensions
該庫是不是免費的,但可以輕鬆地執行主人:
在引擎蓋下,使用SqlBulkCopy。使用擴展方法make比使用每個批量插入的自定義解決方案更容易/更快速。
例
// Easy to use
context.BulkSaveChanges();
// Easy to customize
context.BulkSaveChanges(bulk => bulk.BatchSize = 100);
表現不佳
對不起你越來越表現不佳,
請確保您不包括時間,從一些常見的錯誤,就像忘記JIT編譯,使用Add而不是AddRange影響測試性能,但與我們的庫無關。
當排除所有常見的性能基準測試錯誤時,大多數人報告獲得25-50倍的性能提升。
性能差 – 2017-01-19 21:29:02
你好@Ashraf,請讓我們知道爲什麼你說糟糕的表現。它通常是由與我們的圖書館無關的一些常見錯誤引起的,例如使用Add AddRange – 2017-04-28 13:50:17
。對不起,我的錯誤。我們需要禁用跟蹤緩存。 – 2017-04-29 23:52:24
您可以使用Bulk package庫。 Bulk Insert 1.0.0版本用於Entity框架> = 6.0.0的項目中。 更多的描述可以在下面找到鏈路 Bulkoperation source code
對於EFCore這裏有BulkExtensions(插入,InsertOrUpdate更新,刪除):
鏈接:https://github.com/borisdj/EFCore.BulkExtensions
也可以通過Nuget
的鏈接安裝被打破 – 2014-07-08 12:54:33
@JonBarker - 這裏是GitHub鏈接: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs – DaveHogan 2014-07-09 13:12:30
@DaveHogan我喜歡你在這裏的想法。我們正在播種20萬件以上的東西,至少可以說是痛苦的。我試圖將它放入我們的回購EF種子中,但是當創建一個具有子女對象的辦公室項目時,地址不會創建子項目或關係。這種事情是可能的還是超出了代碼鏈接的範圍?謝謝 – Jon 2014-09-15 11:16:23