Теперь я хочу сделать две вещи:
Сначала выполните один вызов базы данных и получите полный объект (ID, код, значение) для всего списка Branch.
После этого я буду менять «Значение» для каждого объекта.
Затем я хочу сделать один вызов базы данных и сохранить обновленное «Значение» для каждой строки.
Вторая часть проста - просто переместите SaveChanges()
вызов за пределы цикла.
Первая часть хитрая. На момент написания (EF Core 2.0.2) Contains
можно использовать только с одним свойством и объединять в коллекции памяти, запросы на основе Concat
или фильтры типа
.Where(e => listOfBranch.Any(b => b.ID == e.ID && b.Code == e.Code))
все они не переведены в SQL и оцениваются локально.
Единственный способ получить желаемый результат с помощью одного запроса к базе данных - это динамически построить критерии фильтра, подобные этому:
.Where(e =>
(e.ID == listOfBranch[0].ID && e.Code == listOfBranch[0].Code)
||
(e.ID == listOfBranch[1].ID && e.Code == listOfBranch[1].Code)
// ...
||
(e.ID == listOfBranch[N-1].ID && e.Code == listOfBranch[N-1].Code)
)
Вы можете построить вышеупомянутый предикат, используя Expression
методы класса следующим образом (просто замените Record
типом сущности):
var parameter = Expression.Parameter(typeof(Record));
var body = listOfBranch
.Select(b => Expression.AndAlso(
Expression.Equal(Expression.Property(parameter, "ID"), Expression.Constant(b.ID)),
Expression.Equal(Expression.Property(parameter, "Code"), Expression.Constant(b.Code))))
.Aggregate(Expression.OrElse);
var predicate = Expression.Lambda<Func<Record, bool>>(body, parameter);
и использование:
foreach (var record in context.Table.Where(predicate))
{
record.Value = "new value";
}
context.SaveChanges();