Я борюсь с тем, как эффективно структурировать мои запросы 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);
}
Прежде всего вам нужно вызвать Сохранение изменений только один раз в конце метода, и вы можете избежать нулевой ссылки, инициализируя свойства из модели. –
Я не говорю о нулевой ссылке, я говорю о каких-либо элементах, существующих в контексте, пока не зафиксирую изменения. – twilliams