Entity Framework не поддерживает пакетные операции.Мне нравится, как код решает проблему, но даже если он делает именно то, что вы хотите (но для ObjectContext API), это неправильное решение.
Почему это неправильное решение?
Работает только в некоторых случаях.Он определенно не будет работать ни в одном расширенном решении для сопоставления, где сущность сопоставляется с несколькими таблицами (разбиение сущностей, наследование TPT).Я почти уверен, что вы можете найти другие ситуации, в которых он не будет работать из-за сложности запроса.
Он не поддерживает контекст и базу данных.Это проблема любого SQL, выполняемого для БД, но в этом случае SQL скрыт, и другой программист, использующий ваш код, может пропустить его.Если вы удаляете любую запись, которая одновременно загружается в экземпляр контекста, сущность не будет помечена как удаленная и удаленная из контекста (если вы не добавите этот код в свой метод DeleteBatch
- это будет особенно сложно, если удалена записьфактически сопоставляется с несколькими сущностями (разбиение таблицы)).
Наиболее важной проблемой является изменение сгенерированного EF SQL-запроса и предположений, которые вы делаете для этого запроса.Вы ожидаете, что EF назовет первую таблицу, использованную в запросе, как Extent1
.Да, он действительно использует это имя сейчас, но это внутренняя реализация EF.Это может измениться в любом незначительном обновлении EF.Построение собственной логики вокруг внутренних компонентов любого API считается плохой практикой.
В результате вам уже приходится работать с запросом на уровне SQL, чтобы вы могли вызывать запрос SQL напрямую, как показывал @mreyeros, и избегать рисков вэто решение.Вам придется иметь дело с реальными именами таблиц и столбцов, но это то, что вы можете контролировать (ваше отображение может определять их).
Если вы не считаете эти риски значительными, вы можете внести небольшие изменения вкод для работы в DbContext API:
public static class DbContextExtensions
{
public static void DeleteBatch<T>(this DbContext context, IQueryable<T> query) where T : class
{
string sqlClause = GetClause<T>(query);
context.Database.ExecuteSqlCommand(String.Format("DELETE {0}", sqlClause));
}
private static string GetClause<T>(IQueryable<T> clause) where T : class
{
string snippet = "FROM [dbo].[";
string sql = clause.ToString();
string sqlFirstPart = sql.Substring(sql.IndexOf(snippet));
sqlFirstPart = sqlFirstPart.Replace("AS [Extent1]", "");
sqlFirstPart = sqlFirstPart.Replace("[Extent1].", "");
return sqlFirstPart;
}
}
Теперь вы будете вызывать пакетное удаление следующим образом:
context.DeleteBatch(context.People.Where(p => p.Name == "Jim"));