2014-10-08 71 views
0

我需要使用C#和EF(使用.NET 3.5)在數據庫中插入一些對象(約400萬)。我的方法,增加了的對象是在爲:帶EF的批量插入

private DBModelContainer AddToContext(DBModelContainer db, tblMyTable item, int count) 
     { 
      db.AddTottblMyTable (item); 
      if ((count % 10000== 0) || (count == this.toGenerate)) 
      { 
       try 
       { 
        db.SaveChanges(); 
       } 
       catch (Exception e) 
       { 
        Console.WriteLine(e.StackTrace); 
       } 
      } 
      return db; 
     } 

如何從上下文對象分開添加的對象(類型tblMyTable)?我不需要它們以供以後使用,並且當添加超過300000個對象時,db save(db.SaveChanges())之間的執行時間大大增加。

問候

+0

我不認爲使用實體框架批量導入是有效的,你有沒有考慮過使用'SqlBulkCopy'?另外,你可以添加一個如何將實體添加到上下文的代碼示例嗎? – elolos 2014-10-08 08:00:49

+0

而不是「分離」,嘗試關閉更改跟蹤 - AutoDetectChangesEnabled with:context.Configuration.AutoDetectChangesEnabled = false; – reckface 2014-10-08 08:10:51

+0

@reckface context.Configuration.AutoDetectChangesEnabled在.NET 3.5中不可用 – 2014-10-08 08:34:59

回答

2

實體框架可能不適合這種類型的操作的最佳工具。你可能會與普通的ADO.Net,一些存儲過程更好......但如果你不得不使用它,這裏有一些建議:

  • 保持活躍的背景下小圖通過使用新的上下文每個 工作單位
  • 關閉AutoDetechChangesEnabled - context.Configuration.AutoDetectChangesEnabled = false;
  • 配料,在你的循環,調用的SaveChanges定期

編輯

using(var db = new DBModelContainer()) 
    { 
     db.tblMyTable.MergeOption = MergeOption.NoTracking; 
     // Narrow the scope of your db context 
     db.AddTottblMyTable (item); 
     db.SaveChanges(); 
    } 

保持一個長期運行的數據庫環境是不可取的,所以考慮重構你的Add方法跟不上試圖重用相同的上下文。

Rick Strahl's post on bulk inserts for more details

+0

如果我在db.SaveChanges()之後創建新的上下文對象,我得到異常「一個實體對象不能被IEntityChangeTracker的多個實例引用「 – 2014-10-08 11:23:31

+0

我的建議不能與你擁有的模式一起使用:AddToContext(DBModelContainer db ...保持活動的上下文圖形小意味着創建一個上下文,添加實體,調用save更改和處理它(使用context = new DBModelContainer ...我將在回答中詳細解釋 – reckface 2014-10-08 11:40:12

+0

如果我使用這種方法,我會爲每個項目調用save,並且需要更多時間才能添加所有項目。 .. – 2014-10-08 11:55:44

0

你可以試試組的工作和不上的每個記錄插入保存上下文(調用SaveChanges),但將其保存在年底

+0

count變量是要插入的對象的數量。正如你所看到的,只有當我添加了10000個達到要生成的對象總數時,我才調用saveChanges(),而不是每個項目。什麼是工作單位? – 2014-10-08 07:57:09

+1

@BudaGavril,EF DbContext是工作單元模式的實現:http://www.wekeroad.com/2014/03/04/repositories-and-unitofwork-are-not-a-good-idea/ – elolos 2014-10-08 07:59:16

+0

AddRange可能有助於節省時間 DataContext.Entity.AddRange(entityEnumerable); – 2014-10-08 08:04:30

2

阿法克EF不直接支持BulkInsert所以這將是乏味做這樣的東西手動。

儘量考慮EntityFramework.BulkInsert

using (var ctx = GetContext()) 
{ 
    using (var transactionScope = new TransactionScope()) 
    { 
    // some stuff in dbcontext 

    ctx.BulkInsert(entities); 

    ctx.SaveChanges(); 
    transactionScope.Complete(); 
    } 
} 
+0

我的db對象沒有BulkInsert方法。這在.NET 3.5中可用嗎? – 2014-10-08 08:09:23

+0

不是.net 3。5方法,你必須下載https://efbulkinsert.codeplex.com/並編譯爲3.5,然後你將得到3.5的擴展方法 – 2014-10-08 08:11:46

+1

@BudaGavril你也可以通過nuget nuget獲得'Install-Package EntityFramework.BulkInsert- efx'(用版本號4,5或6替換x) – DrCopyPaste 2014-10-08 08:12:30