2016-09-21 55 views
2

我有一個用於批量插入實體框架對象的靜態幫助器方法。它的工作原理和我的單元測試都通過了,但看起來不對,我不禁想到必須有更好的方法來做到這一點。如何從未知狀態的實體框架數據庫連接使用SqlBulkCopy

public static void BulkInsert<T>(Entities db, IList<T> list) 
{ 
    SqlTransaction transaction = db.Database.CurrentTransaction != null ? db.Database.CurrentTransaction.UnderlyingTransaction as SqlTransaction : null; 

    if (db.Database.Connection.State != ConnectionState.Open) 
    { 
     db.Database.Connection.Open(); 
    } 

    using (var bulkCopy = new SqlBulkCopy((db.Database.Connection) as SqlConnection, SqlBulkCopyOptions.Default, transaction)) 
    { 
     //fill a datatable and write to server, this bit works 
    } 
} 

它可以被稱爲DbContextTransaction內部和/或DbContext.Database可能會做的事情已經如此的連接可能已打開。如果不明確打開創建批量複製之前的連接出現錯誤:

System.InvalidOperationException: WriteToServer requires an open and available Connection

這是奇怪的,我還以爲那sqlBulkCopy將已經打開的連接,如果它必須這樣做。

所以我的問題是我正在這個正確的方式嗎?

回答

4

我已經成功地使用了你的方法。
我的感覺是,如果你打開它,你應該再次關閉它。

我還要讓SqlBulkCopy自己處理事務。我不認爲將SqlBulkCopy納入任何環境交易是一個好主意,除非您的特定場景絕對要求它。

public static void BulkInsert<T>(PandaDataContext db, IList<T> list) 
{ 
    var mustOpen = db.Database.Connection.State != ConnectionState.Open; 
    try 
    { 
     if (mustOpen) 
      db.Database.Connection.Open(); 
     using (var bulkCopy = new SqlBulkCopy((db.Database.Connection) as SqlConnection, SqlBulkCopyOptions.Default)) 
     { 
     } 
    } 
    finally 
    { 
     if (mustOpen) 
      db.Database.Connection.Close(); 
    } 
} 
+0

嗨,謝謝,關閉是一個很好的建議。環境事務中唯一的事情是刪除批量複製所替換的行。 – dibs487

+0

如果不會導致損壞或無效的數據,我會獨立刪除行(在不同的事務中)到sqlbulkcopy。如果您必須在同一個事務中同時擁有這兩個數據,請使用實際數據量進行大量測試,並確保它的穩定性和正確性。 – Jim

+0

我在事務中需要它來確保沒有任何內容會讀取它被清除和替換之間的數據。它似乎足夠高性能,不到一百萬行,阻塞2秒無關緊要。爲什麼你對交易中的sqlBulkCopy有懷疑? – dibs487