Какова рекомендуемая практика обновления или удаления нескольких объектов в EntityFramework?
В SQL иногда можно написать что-то вроде
DELETE FROM table WHERE column IS NULL
или
UPDATE table SET column1=value WHERE column2 IS NULL
или любой другой критерий, который может применяться к нескольким строкам.
Насколько я могу судить, лучшая EntityFramework может сделать что-то вроде
foreach (var entity in db.Table.Where(row => row.Column == null))
db.Table.Remove(entity); // or entity.Column2 = value;
db.SaveChanges();
Но, конечно, это приведет к извлечению всех объектов и последующему запуску отдельного запроса DELETE для каждого. Разумеется, это должно быть намного медленнее, если существует множество объектов, удовлетворяющих критерию.
Итак, сократите длинную историю, есть ли поддержка в EntityFramework для обновления или удаления нескольких объектов в одном запросе?
Ответы
Ответ 1
EF не поддерживает пакетные обновления или удаления, но вы можете просто:
db.Database.ExecuteSqlCommand("DELETE FROM ...", someParameter);
Edit:
Люди, которые действительно хотят придерживаться запросов LINQ, иногда используют обходной путь, когда они сначала создают выбор SQL-запроса из запроса LINQ:
string query = db.Table.Where(row => row.Column == null).ToString();
и после этого найдите первое вхождение FROM
и замените начало запроса на DELETE
и выполните результат с помощью ExecuteSqlCommand
. Проблема с этим подходом заключается в том, что он работает только в основных сценариях. Он не будет работать с разбиением объектов или некоторым наложением, когда вам нужно удалить две или более записей на сущность.
Ответ 2
Взгляните на Расширения платформы Entity (несколько обновлений сущностей). Этот проект позволяет выполнять операции с использованием лямбда-выражений. Примеры из документа:
this.Container.Devices.Delete(o => o.Id == 1);
this.Container.Devices.Update(
o => new Device() {
LastOrderRequest = DateTime.Now,
Description = o.Description + "teste"
},
o => o.Id == 1);
Копаем исходный код проекта EFE вы можете увидеть, как автоматизировать второй подход @Ladislav Mrnka и добавить операции настройки:
public override string GetDmlCommand()
{
//Recover Table Name
StringBuilder updateCommand = new StringBuilder();
updateCommand.Append("UPDATE ");
updateCommand.Append(MetadataAccessor.GetTableNameByEdmType(
typeof(T).Name));
updateCommand.Append(" ");
updateCommand.Append(setParser.ParseExpression());
updateCommand.Append(whereParser.ParseExpression());
return updateCommand.ToString();
}
Отредактировано 3 года назад
Взгляните на этот отличный ответ: fooobar.com/questions/133130/...
Ответ 3
Расширенная библиотека расширенной платформы Entity Framework.
Удалить
//delete all users where FirstName matches
context.Users.Delete(u => u.FirstName == "firstname");
Update
//update all tasks with status of 1 to status of 2
context.Tasks.Update(
t => t.StatusId == 1,
t2 => new Task {StatusId = 2});
//example of using an IQueryable as the filter for the update
var users = context.Users.Where(u => u.FirstName == "firstname");
context.Users.Update(users, u => new User {FirstName = "newfirstname"});
https://github.com/loresoft/EntityFramework.Extended