Массовое удаление строк с помощью RemoveRange()

Я пытаюсь удалить несколько строк из таблицы.

В обычном SQL Server это было бы просто:

DELETE FROM Table
WHERE
    Table.Column = 'SomeRandomValue'
    AND Table.Column2 = 'AnotherRandomValue'

В Entity Framework 6 они внедрили метод RemoveRange().
Однако, когда я использую его, вместо того, чтобы удалять строки, используя предложения where, которые я предоставил, Entity Framework запрашивает базу данных, чтобы получить все строки, которые соответствуют предложениям where и удаляют их один за другим, используя их первичные ключи.

Является ли это текущим ограничением EntityFramework? Или я использую RemoveRange() неправильно?

Ниже я использую RemoveRange():

db.Tables.RemoveRange(
    db.Tables
        .Where(_ => _.Column == 'SomeRandomValue'
            && _.Column2 == 'AnotherRandomValue')
);

Ответ 1

Я думаю, что мы достигли здесь ограничения EF. Иногда вам просто нужно использовать ExecuteSqlCommand, чтобы оставаться работоспособным.

Ответ 2

То, что вы ищете, представляет собой библиотеку пакетного удаления, которая удаляет несколько записей в базе данных из запроса LINQ без загрузки объектов.

Существует несколько библиотек, поддерживающих эту функцию.

Вы можете найти список здесь: Библиотека пакетной библиотеки Entity Framework

Отказ от ответственности: Я являюсь владельцем проекта Entity Framework Plus

// using Z.EntityFramework.Plus; // Don't forget to include this.

// DELETE directly in SQL (without loading entities)
db.Tables.Where(_ => _.Column == 'SomeRandomValue'
                     && _.Column2 == 'AnotherRandomValue')
         .Delete();

// DELETE using a BatchSize      
db.Tables.Where(_ => _.Column == 'SomeRandomValue'
                     && _.Column2 == 'AnotherRandomValue')
         .Delete(x => x.BatchSize = 1000);

Wiki: EF + Batch Delete

Ответ 3

Немного сломано, попробуйте

db.Tables.RemoveRange(
    db.Tables
        .Where(_ => _.Column == 'SomeRandomValue'
            && _.Column2 == 'AnotherRandomeValue').AsEnumerable().ToList()
);
db.SaveChanges();

Ответ 4

var db1 =  db.Tables
        .Where(_ => _.Column == 'SomeRandomValue'
            && _.Column2 == 'AnotherRandomeValue').AsEnumerable().ToList();
db.Tables.RemoveRange(db1);
db.SaveChanges();

Используйте переменную для сохранения списка Съемника и передайте ее в RemoveRange().

Я обычно делаю так, и это работает. Надеюсь, это также будет работать в вашем случае.

Ответ 5

Почему бы вам просто не подключить адаптер к базе данных и просто отправить соответствующую команду удаления, как в вашем примере?

Ответ 6

Отступите и подумайте. Вы действительно хотите загрузить записи из базы данных, чтобы удалить их? Просто потому, что вы можете сделать это не очень хорошо.

Возможно, вы могли бы рассмотреть возможность удаления элементов из базы данных с помощью хранимой процедуры? EF также позволяет это делать...

Ответ 7

Я имею дело с этим сам, и соглашусь с Ади - просто используйте sql.

Я очищаю старые строки в таблице журналов, а EF RemoveRange занял 3 минуты, чтобы сделать то же самое в 3 секунды:

DELETE FROM LogEntries WHERE DATEDIFF(day, GETDATE(), Date) < -6

Дата - это имя столбца, содержащего дату. Чтобы сделать его правильным, используйте параметр, конечно, следующим образом:

  context.Database.ExecuteSqlCommand
      ("DELETE FROM  LogEntries WHERE DATEDIFF(day, GETDATE(), Date) < @DaysOld", new System.Data.SqlClient.SqlParameter(
                        "DaysOld", - Settings.DaysToKeepDBLogEntries));

Обратите внимание, что в моем случае есть много строк. Когда я начал проект и не имел большого количества данных, RemoveRange работал нормально.