Какова рекомендуемая практика обновления или удаления нескольких объектов в EntityFramework? - PullRequest
25 голосов
/ 19 марта 2012

В 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 для обновления или удаления нескольких объектов в одном запросе?

Ответы [ 3 ]

13 голосов
/ 20 марта 2012

EF не поддерживает пакетные обновления или удаления, но вы можете просто сделать:

db.Database.ExecuteSqlCommand("DELETE FROM ...", someParameter);

Edit:

Люди, которые действительно хотят придерживаться запросов LINQ, иногда используют обходной путь, когда они сначала создают запрос SQL выбора из запроса LINQ:

string query = db.Table.Where(row => row.Column == null).ToString();

и после этого найдите первое вхождение FROM, замените начало запроса на DELETE и выполните результат на ExecuteSqlCommand. Проблема этого подхода заключается в том, что он работает только в базовых сценариях. Он не будет работать с разделением сущностей или отображением наследования, когда вам нужно удалить две или более записей на сущность.

5 голосов
/ 20 марта 2012

Посмотрите на Расширения Entity Framework (несколько обновлений сущностей) . Этот проект позволяет задавать операции с использованием лямбда-выражений. Образцы из документа:

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 года спустя

Посмотрите на этот замечательный ответ: https://stackoverflow.com/a/12751429

2 голосов
/ 04 октября 2014

Расширенная библиотека Entity Framework помогает сделать это.

Удалить

//delete all users where FirstName matches
context.Users.Delete(u => u.FirstName == "firstname");

Обновление

//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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...