Ответ 1
Я думаю, что мы достигли здесь ограничения EF. Иногда вам просто нужно использовать ExecuteSqlCommand, чтобы оставаться работоспособным.
Я пытаюсь удалить несколько строк из таблицы.
В обычном 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')
);
Я думаю, что мы достигли здесь ограничения EF. Иногда вам просто нужно использовать ExecuteSqlCommand, чтобы оставаться работоспособным.
То, что вы ищете, представляет собой библиотеку пакетного удаления, которая удаляет несколько записей в базе данных из запроса 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
Немного сломано, попробуйте
db.Tables.RemoveRange(
db.Tables
.Where(_ => _.Column == 'SomeRandomValue'
&& _.Column2 == 'AnotherRandomeValue').AsEnumerable().ToList()
);
db.SaveChanges();
var db1 = db.Tables
.Where(_ => _.Column == 'SomeRandomValue'
&& _.Column2 == 'AnotherRandomeValue').AsEnumerable().ToList();
db.Tables.RemoveRange(db1);
db.SaveChanges();
Используйте переменную для сохранения списка Съемника и передайте ее в RemoveRange().
Я обычно делаю так, и это работает. Надеюсь, это также будет работать в вашем случае.
Почему бы вам просто не подключить адаптер к базе данных и просто отправить соответствующую команду удаления, как в вашем примере?
Отступите и подумайте. Вы действительно хотите загрузить записи из базы данных, чтобы удалить их? Просто потому, что вы можете сделать это не очень хорошо.
Возможно, вы могли бы рассмотреть возможность удаления элементов из базы данных с помощью хранимой процедуры? EF также позволяет это делать...
Я имею дело с этим сам, и соглашусь с Ади - просто используйте 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 работал нормально.