2012-01-16 1 views
11

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

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

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

Вот мой Extension:

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 не всегда возвращает правильное имя. [Пример заказа] является примером).
  • По завершении этого, я нашел это http://msmvps.com/blogs/matthieu/archive/2010/05/21/bulk-delete-v3.aspx, но не смог заставить его работать в любом случае. Не удалось получить исключение NotImplementedException из контекста, являющегося нулевым.
  • Удалить с помощью команды join не работает. Я тестирую SQL Server Compact 3.5, возможно, это ограничение.

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

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

+4

Пожалуйста, взгляните на [вопрос] [1]. [1]: http://stackoverflow.com/questions/8538899/ –

+0

Вы считали RemoveRange в EF6? Я хотел бы знать, насколько это «оптимизировано» и что он работает. http://msdn.microsoft.com/en-us/library/system.data.entity.dbset.removerange(v=vs.113).aspx – Colin

+0

Получение имени таблицы из метаданных - http://stackoverflow.com/a/18964974/150342 – Colin

ответ

8
  1. Установка Entity Framework Extended Library (PM> Install-Package EntityFramework.Extended)

  2. Импорт EntityFramework.Extensions в коде

  3. Удаление записи, указанные внутреннего запроса

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

Удалить s все записи внутри Заказы с userID = 1

+0

Это так НЕ в духе EntityFramework, ограниченное определенным провайдером (SQL-Server). – springy76

5

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

Чтобы удалить свойства навигации товаров из заказа 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(); 

Надеется, что это помогает.

+3

При переходе к следующему элементу в перечислении он выдается с ошибкой «Элемент, измененный из списка, не подходит для дальнейшего перечисления. – DOM

+0

Он не работает в Entity v5 –

+0

Я не знаю, почему @DOM говорит, что он не работает. Он отлично работает, если вы не забыли вызвать метод ToList(). – NoobDeveloper

Смежные вопросы