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);
}
まず、メソッドの最後に一度だけ変更を保存する必要があります。また、モデルからプロパティを初期化することでnull参照を避けることができます。 –
私はヌルリファレンスについては言及していません、私は変更をコミットするまで、コンテキスト内に存在する項目については何も話していません。 – twilliams