Насколько я знаю, EF 6 представил параметр .RemoveRange() в вашем DbContext. Короче говоря, вы можете сделать что-то вроде следующего:
var db = new MyDbContext();
var itemsToDelete = db.MyTable.Where(x=>!x.active);
db.MyTable.RemoveRange(itemsToDelete);
db.SaveChanges();
Таким образом, вместо того, чтобы выполнять какие-либо операции foreach
, вы можете использовать этот новый метод расширения. С вашим контекстом Unit Of Work у вас может быть перегрузка вашего метода Delete
, который принимает IEnumerable (?*) вместо одного объекта Test
, как ваш текущий метод. Эта новая перегрузка должна вызывать функцию RemoveRange()
в DbContext.
?* - Это зависит от того, что возвращает GetTests()
, но я думаю, что IEnumerable<>
охватывает как IList<>
, так и IQueryable<>
Изменить
Пара комментариев. Во-первых, я бы не стал вызывать .ToList()
перед выдачей RemoveRange
, так как вы не хотите фактически получать элементы для своей службы. Это должно помочь сократить время выполнения. Во-вторых, вы правы в том, что вы все равно будете выдавать 1000 операторов удаления. Однако повышение производительности достигается за счет отказа от вызова ChangeTracker в EF для каждого отдельного элемента, который вы удаляете из файла DbSet
. Из журнала MSDN:
AddRange и RemoveRange Как упоминалось ранее, AddRange и RemoveRange являются вкладом члена сообщества Zorrilla. Каждый метод принимает в качестве параметра перечисляемый объект одного типа. В первом примере кода в разделе совместного использования DbTransactions я использовал AddRange при передаче массива экземпляров Casino:
context.Casinos.AddRange(new[] {казино1, казино2}); Эти методы выполняются намного быстрее, чем добавление или удаление одного объекта за раз, поскольку по умолчанию Entity Framework вызывает DetectChanges в каждом методе добавления и удаления. С помощью методов Range вы можете обрабатывать несколько объектов, в то время как DetectChanges вызывается только один раз, что значительно повышает производительность. Я тестировал это, используя пять, 50, 500, 5000 и даже 50 000 объектов, и, по крайней мере, в моем сценарии нет ограничений на размер массива — и это впечатляюще быстро! Имейте в виду, что это улучшение имеет значение только для того, чтобы контекст воздействовал на объекты, и не имеет отношения к SaveChanges. Вызов SaveChanges по-прежнему выполняет только одну команду базы данных за раз. Таким образом, хотя вы можете быстро добавить 50 000 объектов в контекст, вы все равно получите 50 000 команд вставки, выполняемых по отдельности при вызове SaveChanges — вероятно, это не то, что вы хотите делать в реальной системе.
С другой стороны, велись долгие дискуссии о реализации поддержки массовых операций без необходимости отслеживания объектов с помощью EF (bit.ly/16tMHw4), а также о пакетных операциях, позволяющих отправлять несколько команд вместе за один вызов базы данных. (bit.ly/PegT17). Ни одна из функций не вошла в первоначальный выпуск EF6, но обе важны и запланированы для будущего выпуска.
Если вы действительно хотите выполнить только одну команду базы данных, вам подойдет либо хранимая процедура с использованием необработанных операторов SQL, поскольку EntityFramework не поддерживает массовые транзакции. Однако использование элементов RemoveRange
и AddRange
(особенно если, как вы сказали, нечасто) сэкономит вам много времени по сравнению с вызовом Remove()
в цикле foreach.
person
Tommy
schedule
05.02.2014