2016-07-13 1 views
0

LINQクエリを効率的に構築する方法に苦労して、データベースへの往復呼び出しの回数を最小限に抑えることができます。多くのエンティティを作成するための効率的な方法が必要

以下のコードを使用すると、これらのオブジェクト作成のそれぞれは、多数のオープンおよびクローズデータベース接続を生成できます。

データベースへの呼び出しを最小限に抑え、単一の呼び出しでさらにオブジェクトを挿入するために、このコードの一部を再構成することはできますか?

私はSaveChangesを複数回呼び出すことに頼ったことがあります。変更を保存するまで、コンテキストに存在しないオブジェクトの問題にします。

public IActionResult AddSnapshots([FromBody]List<MembershipSnapshot> snapshots, bool? update = false) 
     { 
      if (!ModelState.IsValid) { return new BadRequestObjectResult(ModelState); } 
      if (snapshots.Count == 0) 
      { 
       ModelState.AddModelError("Empty", "There were no records provided to be inserted."); 
       return new BadRequestObjectResult(ModelState); 
      } 

      // Get the composite keys from the supplied list 
      var snapshotKeys = snapshots.Select(s => new { s.MembershipYear, s.DataDate, s.Aggregate }).ToArray(); 
      // Find which records already exist in the database, pulling their composite keys 
      var snapshotsInDb = platformContext.MembershipSnapshots.Where(s => snapshotKeys.Contains(new { s.MembershipYear, s.DataDate, s.Aggregate })) 
               .Select(s => new { s.MembershipYear, s.DataDate, s.Aggregate }).ToArray(); 
      // And filter them out, so we remain with the ones that don't yet exist 
      var addSnapshots = snapshots.Where(s => !snapshotsInDb.Contains(new { s.MembershipYear, s.DataDate, s.Aggregate })) 
       .ToList(); 
      platformContext.MembershipSnapshots.AddRange(addSnapshots); 
      platformContext.SaveChanges(); 

      // In addition to adding all of the snapshots that didn't exist, we'll populate the 
      // membership categories, aggregates and aggregate collections if they don't already exist 
      var aggregates = snapshots.Select(s => new { Name = s.Aggregate, Category = s.AggregateCategory }).Distinct(); 

      var addAggregates = aggregates.Where(a => !platformContext.MembershipAggregates.Any(ma => ma.Name == a.Name)) 
              .GroupBy(a => a.Name).Select(g => g.First()) 
              .Select(a => new Aggregate { Name = a.Name }); 
      platformContext.AddRange(addAggregates); 
      platformContext.SaveChanges(); 

      var addCategories = aggregates.Where(a => !platformContext.MembershipCategories.Any(c => c.Name == a.Category)) 
              .GroupBy(a => a.Category).Select(g => g.First()) 
              .Select(a => new Category { Name = a.Category }); 
      platformContext.AddRange(addCategories); 
      platformContext.SaveChanges(); 

      var addAggregateCollection = aggregates.Where(a => !platformContext.AggregateCollections.Any(ma => ma.Name == a.Name)) 
                .GroupBy(a => a.Name).Select(g => g.First()) 
                .Select(a => new AggregateCollection() 
                { 
                 Name = a.Name, 
                 Category = platformContext.MembershipCategories.Where(c => c.Name == a.Category).Single(), 
                 Description = a.Name, 
                 AggregateCollectionAggregates = new List<AggregateCollectionAggregate>() 
                 { 
                  new AggregateCollectionAggregate() 
                  { 
                   Aggregate = platformContext.MembershipAggregates.Where(ma => ma.Name == a.Name).Single() 
                  } 
                 } 
                }); 
      platformContext.AddRange(addAggregateCollection); 
      platformContext.SaveChanges(); 

      return new StatusCodeResult(StatusCodes.Status200OK); 
     } 
+0

まず、メソッドの最後に一度だけ変更を保存する必要があります。また、モデルからプロパティを初期化することでnull参照を避けることができます。 –

+0

私はヌルリファレンスについては言及していません、私は変更をコミットするまで、コンテキスト内に存在する項目については何も話していません。 – twilliams

答えて

1

メイトは、あなたがレストランでウェイターたいDbContextのものにする必要があります。

あなたがレストランでの10人の友人と一緒にいる場合は、ウェイターは男のコックに情報を与えるために台所にを行く、その後、最初の友人のオーダーを取って来てないが、その後、来ています2人目の友人のために戻ってもう一度キッチンまで... (そういう場合は別のレストランに行ってください)。

ウェイターがあなたのテーブルに来て、彼が必要とするすべての情報を取得し、男の料理人になるだろうされ

、DbContextと同じ、あなたが望むようあなたができるだけ多くの新しいオブジェクトを追加することができ、それはそれぞれについて知っているだろう新しいオブジェクトを作成し、オブジェクトを初期化する限り、不平を言うことはありません。

ウェイターのように、良いウェイターは彼らが持っているものとあなたに与えることができるものを知っていれば、他のワインを頼むと彼は最初から "いいえ、持っていない"良いウェイターであり、常に彼が持っているかどうかを知っている。 Dbcontextが良いとするには、彼女にそれぞれのオブジェクトについて何を期待するかを伝える必要があります。

ex。初期化の

public class Lunch 
    { 
     public IEnumerable<Meat> Meat { get; set; } = new List<Meat>(); 
     public Desert Desert { get; set; } = new Desert(); 
     public DateTime DateTime { get; set; } = DateTime.Now; 
     public bool WaiterIsFriendly { get; set; } = true; 
    } 

DbContextを使用して作業する方法をご希望ですか!!!

編集:

私は昼食という名前の私のDbContextでエンティティを持っている場合は、私は次の操作を実行できます。

var lunch1=new Lunch(); 
Context.Lunch.Add(lunch1); 
    lunch1.Desert=new Desert(); 
    lunch1.Meat.add(new Meat()); 

    var lunch2=new Lunch(); 
Context.Lunch.Add(lunch2); 
    lunch2.Desert=new Desert(); 
    lunch2.Meat.add(new Meat()); 

と終わりに、私は(Context.SaveChangesを言うことができます)。

すべてこれは、ランチクラスのDesert、Meat ...を初期化した場合にのみ発生します。

+0

=創造的な例のために=) – Progressive

+0

この答えがテーブルにもたらすものは本当にわかりません。私はDbContextを利用する方法を理解しています。私が新たに作成したオブジェクトをAddRangeのコンテキストに追加すると、他のコードでアクセスすることができなくなります。データセットは空です。さらに、それは問題の一部に過ぎません。コンテキスト上の単一のSaveChangesであっても、他のすべてが正しい場合でも、データベースはAddRangeを介して追加されたすべての単一オブジェクトの接続を開始および終了しています。 200個のオブジェクトを追加すると、データベースは現在のコードで200回開いたり閉じたりします。 – twilliams

関連する問題