我有一個實體列表,我想將它們插入到數據庫中。如果實體已經存在於數據庫中,那麼它需要被跳過。如果它在數據庫中但具有不同的值,則需要更新它。使用實體框架進行批量插入/更新的有效方法
有沒有辦法做到這一點,而不是每個項目做一個數據庫調用?
我的計劃是嘗試一個插入,如果一個唯一的約束異常的關鍵是拋出然後做一個更新。
我有一個實體列表,我想將它們插入到數據庫中。如果實體已經存在於數據庫中,那麼它需要被跳過。如果它在數據庫中但具有不同的值,則需要更新它。使用實體框架進行批量插入/更新的有效方法
有沒有辦法做到這一點,而不是每個項目做一個數據庫調用?
我的計劃是嘗試一個插入,如果一個唯一的約束異常的關鍵是拋出然後做一個更新。
只是不要在這種情況下使用實體框架。只需使用存儲過程(如何取決於您使用EF的版本/方法,您可能需要擴展您的DbContext
或添加實體模型的映射)。
如果您使用的SQL Server,然後在你的存儲過程,使用該MERGE
命令有效不正是你需要:insert,如果它不存在,或者更新,如果它。一切都在一個高效的SQL查詢中。
如果使用SqlBulkCopy,它不能全部在單個查詢中。它需要是一個sp來創建臨時表,然後是一個sp來完成與中間的.net內容的合併。 –
@IanWarburton爲什麼你需要'SqlBulkCopy'? SQL'Merge'命令可以滿足您的所有需求。你可以通過傳遞你的實體作爲參數來調用一個存儲過程(例如表值參數),'Merge'將完成所有的工作。 – ken2k
表值參數...是很酷。 –
EF不適用於BULK插頁。 對於1000年的記錄它可以,但大數字(100k加)它的速度慢。
如果您打算使用EF。
如
Context.Set<TPoco>().AddOrUpdate(poco);
//...
Context.Configuration.AutoDetectChangesEnabled =
//..
Context.SaveChanges();
如果複製無關的數據,你可以嘗試在平行(DOH)這些表
我認爲如果在批處理中存在唯一的約束異常,那將會很尷尬。 –
如果您可能有許多獨特的約束違規,那麼批量提交的確不太有用。其實關於保存數據包的評論是建議你保持它們小,最大1000不太大。如果沒有完整的腹部應付。如果吞吐量正常,請使用單個記錄提交。您還可以嘗試使用較小的數據包,例如10個,如果失敗,則重試單個數據包。只是各種事情,我試圖獲得更好的吞吐量。 –
我已經爲 https://efbulkinsert.codeplex.com/
的延伸,它是非常簡單的使用
using(var context = new MyDbContext())
{
context.BulkInsert(hugeCollectionOfEntities);
}
只是擡頭:這個庫不支持導航屬性。如果您有父/子表關聯,插入後子表元素的外鍵將被設置爲0 –
這不處理事物的更新方面。 –
它是免費的嗎?或者我需要爲它付費嗎?。這是一樣的http://entityframework-extensions.net/#pro? –
創建臨時表: 的SqlCommand(的String.Format(「SELECT TOP 0 * INTO {0} FROM {1} ...
將數據批量插入到它中 - 上面提到的實體框架擴展需要進行調整以支持臨時表名,但其他方面是正確的 - 或者滾動一些代碼並使用SqlBulkCopy。
構造MERGE語句。
如果你是我的一個屬性列表,你可以使(2)和(3)通用。我可以在大約20秒內讀取併合並150,000行。
[在實體框架中插入的最快方式]的可能重複(http://stackoverflow.com/questions/5940225/fastest-way-of-inserting-in-entity-framework) –
這裏是非常好的答案。 [http://stackoverflow.com/questions/5940225/fastest-way-of-inserting-in-entity-framework][1] [1]:HTTP://計算器。 com/questions/5940225 /插入實體框架的最快方式 –