Удаление нескольких записей с помощью Entity Framework с использованием одного запроса LINQ

Я пытаюсь выполнить DELETE с помощью LINQ, который будет генерировать один запрос.

Вот как я это делаю:

// NorthwintEntities is an ADO.NET Entitity Data Model
var northwindEntities = new NorthwindEntities();
northwindEntities.Order_Details.Delete(o => o.Order_ID == 11076);

Здесь мое расширение:

public static class EntityExtensions
{
    private static Regex rxTableName = new Regex(@"^FROM\s+(?<table>\[[^\]]*\](\.\[[^\]]*\]){0,2})\s+AS\s+(?<alias>\[[^\]]*\])", RegexOptions.Multiline);

    public static void Delete<T>(this ObjectSet<T> entity, Expression<Func<T, bool>> expression) where T : EntityObject
    {
        var selectQuery = entity.Where(expression).Select(x => 1);

        string selectQueryString = ((ObjectQuery)selectQuery).ToTraceString();

        string deleteQueryString = ConvertSqlSelectToDelete(selectQueryString);

        entity.Context.ExecuteStoreCommand(deleteQueryString);
    }

    private static string ConvertSqlSelectToDelete(string selectQuery)
    {
        if (selectQuery.IndexOf(" JOIN ") > -1)
        {
            throw new Exception("Query with JOIN is not supported: " + selectQuery);
        }

        Match match = rxTableName.Match(selectQuery);
        if (!match.Success)
        {
            throw new Exception("Unable to convert SELECT: " + selectQuery);
        }

        string deleteQuery = "DELETE \r\n" + selectQuery.Substring(match.Index);
        deleteQuery = deleteQuery.Replace(match.Groups["alias"].Value + ".", "");
        deleteQuery = deleteQuery.Replace("AS " + match.Groups["alias"].Value, "");

        return deleteQuery;
    }
}

Это работает, но у меня есть несколько комментариев.

  • Я не большой поклонник использования Regex здесь, но это был единственный способ получить имя таблицы. (entity.EntitySet.Name не всегда будет возвращать правильное имя. [Order Details] является примером).
  • После этого я нашел http://msmvps.com/blogs/matthieu/archive/2010/05/21/bulk-delete-v3.aspx, но не смог заставить его работать. Не удалось получить исключение NotImplementedException из нулевого контекста.
  • Удалить с помощью соединения, похоже, не работает. Я тестирую SQL Server Compact 3.5, возможно, это ограничение.

Итак, мои вопросы: есть ли более простой способ сделать это? Если да, то что это такое?

Любая помощь вообще будет оценена.

Ответ 1

  • Установить расширенную библиотеку Entity Framework (PM > Install-Package EntityFramework.Extended)

  • Импортировать EntityFramework.Extensions в свой код

  • Удалить записи, указанные внутренним запросом

    context.Orders.Where(o=>o.User_ID == 1).Delete();
    

Удаляет все записи внутри Заказы с идентификатором пользователя = 1

Ответ 2

Один способ иметь пакетное удаление - установка ВКЛЮЧЕНА КАСКАДОМ DELETE на внешние ключи. Вам нужно установить CASCADE на отношение в дизайнере и установить ON CASCADE DELETE по отношению к базе данных.

Чтобы удалить свойства навигации товаров из Order EF, сделайте (количество свойств продуктов) +1 операторов в базе данных.

Я предпочитаю это делать:

var order = context.Orders.Include(p=>p.Products).Where(o=>o.Order_ID == 11076);

foreach(Product product in order.Products.ToList())
{
  context.Entry(product).State = EntityState.Deleted;
}
context.Entry(order ).State = EntityState.Deleted;
context.SaveChanges();

Надеюсь, что это поможет.