Ответ 1
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<>
Edit
Несколько комментариев. Во-первых, я бы не назвал .ToList()
перед выпуском RemoveRange
, так как вы не хотите, чтобы вы действительно загружали элементы в свою службу. Это должно помочь сократить время выполнения. Во-вторых, вы правы, как бы то ни было, что вы все равно будете выдавать 1000 операторов удаления. Однако прирост производительности обусловлен тем, что вы не вызываете ChangeTracker в EF для каждого отдельного элемента, который вы удаляете из DbSet
. Из журнала MSDN:
AddRange и RemoveRange Как упоминалось ранее, AddRange и RemoveRange - это вклад членов сообщества Zorrilla. каждый метод принимает в качестве своего параметра перечислимый тип одного объекта. В первом примере кода в разделе совместного использования DbTransactions я использовал AddRange, когда я передал массив экземпляров казино:
context.Casinos.AddRange(новый [] {casino1, casino2}); Эти методы выполняются намного быстрее, чем добавление или удаление одного объекта за раз потому что по умолчанию Entity Framework вызывает DetectChanges в каждом добавлении и Удалить. С помощью методов Range вы можете обрабатывать несколько объекты, в то время как DetectChanges вызывается только один раз, улучшая производительность драматически. Ive проверил это, используя пять, 50, 500, 5000 и даже 50 000 объектов и, по крайней мере, в моем сценарии, нет ограничений для размер массива - и его впечатляюще быстро! Имейте в виду, что это улучшение имеет значение только для того, чтобы контекст воздействовал на объектов и не имеет отношения к SaveChanges. Вызов SaveChanges по-прежнему выполняет только одну команду базы данных за раз. Поэтому, пока вы можете быстро добавьте 50 000 объектов в контекст, вы все равно получите 50 000 вложений команды, выполняемые индивидуально, когда вы вызываете SaveChanges, возможно, не то, что вы хотите сделать в реальной системе.
С другой стороны, были длительные дискуссии о реализация поддержки массовых операций без необходимости отслеживать EF (бит .ly/16tMHw4) и для пакетных операций для включения отправка нескольких команд вместе в одном вызове в базу данных (Bit.ly/PegT17). Ни одна из функций не попала в исходную версию EF6, но оба они важны и предназначены для будущего выпуска.
Если вы действительно хотите только выдавать одну команду базы данных, либо хранимая процедура использования необработанных SQL-операторов будет способом, так как EntityFramework не поддерживает массовые транзакции. Однако использование элементов RemoveRange
и AddRange
(особенно если, как вы сказали, нечасты), сэкономит вам много времени по сравнению с вызовом Remove()
в цикле foreach.