2017-07-13 11 views
0

次のコードブロックは、基本的にDB内のエンティティの存在をチェックし、更新のためにコンテキストにロードするか、存在しない場合は新しいエンティティを追加します。EF6でUPSERTを実行するより効率的な方法

using (var db = new Entities.DB.DConn()) 
{ 
    //... 
    foreach (Account account in accounts) 
    { 
     bool isNewRecord = false; 
     Entities.DB.Account dlAccount = new Entities.DB.Account(); 
     Entities.DB.Account exisitngAcct = db.Accounts.Where(x => x.GId == dlG.Id).FirstOrDefault(); //x.GId is NOT ad primary key 
     if (exisitngAcct != null) 
     { 
      dlAccount = exisitngAcct; 
      isNewRecord = true; 
     } 

     dlAccount.GId = dlG.Id; 
     dlAccount.AccountName = account.NameAtFI; 
     dlAccount.AccountNumber = account.AcctNumber; 
     dlAccount.AcctType = account.AcctType; 
     dlAccount.AsOfDate = account.DateCreated; 
     dlAccount.IsDeleted = false; 
     dlAccount.DateModified = DateTime.UtcNow.ToUniversalTime(); 

     if (isNewRecord) 
     { 
      dldb.Accounts.Add(dlAccount); 
     } 

     db.SaveChanges(); 
    } 
} 

私は、コンテキストにエンティティを取り付け、EntityStateを使用しての研究の負荷をやっている、しかし、私はちょうどそのコードは、私の例で書かれたことだろうか届きません。

上記と同じ操作をより効率的に実行できる方法を教えてもらえますか?私はEFにとってかなり新しく、私が正しくそれを使って作業していることを確認したい。

ご協力いただきありがとうございます。

+0

-であるとして、あなたのコードについて "非効率的" とは何ですか? – Amy

+0

おそらく何もありません。私は私が知らないものを知らない。 – Nugs

答えて

2

EFの設計者は、使用していないエンティティを使用しているため、このエンティティを使用している開発者は作業を進めませんでした。このように、「適切な」方法はありません。すべてがユースケースとエンティティモデルに依存します。

既存のレコードを強制的に更新するように見えるので(DateModifiedを設定して)、既存のデータをコンテキストに読み込む必要はありません。単一のデータベース旅で既存のエンティティのPKを取得し、追加または更新のための基準として使用するのに十分である:

using (var db = new Entities.DB.DConn()) 
{ 
    //... 
    var accountIds = accounts.Select(x => x.GId); // variable required by EF6 Contains translation 
    var existingAccountIds = new HashSet<GId_Type>(
     db.Accouns.Where(x => accountIds.Contains(x.GId).Select(x => x.GId)); 
    foreach (Account account in accounts) 
    { 
     var dlAccount = new Entities.DB.Account(); 
     dlAccount.GId = account.GId; 
     dlAccount.AccountName = account.NameAtFI; 
     dlAccount.AccountNumber = account.AcctNumber; 
     dlAccount.AcctType = account.AcctType; 
     dlAccount.AsOfDate = account.DateCreated; 
     dlAccount.IsDeleted = false; 
     dlAccount.DateModified = DateTime.UtcNow.ToUniversalTime();  
     if (existingAccountIds.Contains(dlAccount.GId)) 
      db.Entry(dlAccount).State = EntityState.Modified; // update 
     else 
      db.Accounts.Add(dlAccount); // insert 
    } 
    db.SaveChanges(); 
} 

(などGIdの種類、例えばintGuidGId_Typeを置き換える)

SaveChangesをループ外に移動すると、このシナリオでは最高のパフォーマンスが得られます。

+0

ニース!返信Ivanに感謝します! – Nugs

0

パフォーマンスを改善する方法がいくつかあります。例として、@Ivanソリューションを使用して一度に複数のアカウントを取得してデータベースの往復回数を減らす

ただし、SaveChangesメソッドは、追加する必要があるすべてのエンティティに対して1回のデータベース往復を行います。 INSANELYが遅い更新です。


免責事項:私はプロジェクトEntity Framework Extensions

このライブラリの所有者は無料ではありませんよ。しかし、それはupsert操作を実行する最も効率的な方法です。

  • BulkSaveChanges
  • BulkInsert
  • BulkUpdate
  • のbulkdelete
  • BulkMerge
  • BulkSynchronize:

    バルクマージ(アップサート)の他に、このライブラリには、あなたはすべての一括操作を実行することができます

例:

// Easy to use 
context.BulkSaveChanges(); 

// Easy to customize 
context.BulkSaveChanges(bulk => bulk.BatchSize = 100); 

// Perform Bulk Operations 
context.BulkDelete(customers); 
context.BulkInsert(customers); 
context.BulkUpdate(customers); 

// Customize Primary Key 
context.BulkMerge(customers, operation => { 
    operation.ColumnPrimaryKeyExpression = 
     customer => customer.Code; 
}); 
関連する問題