2012-01-16 4 views
11

단일 쿼리를 생성하는 LINQ를 사용하여 DELETE를 수행하려고합니다.단일 LINQ 쿼리를 사용하여 Entity Framework로 여러 레코드 삭제

// 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이 발견되었지만 어쨌든 작동하지 않습니다. null 인 컨텍스트로부터의 NotImplementedException의 취득을 보관 유지합니다.
  • 가입을 통한 삭제가 작동하지 않는 것 같습니다. SQL Server Compact 3.5를 테스트하고 있습니다. 아마도 그 한계가 있습니다.

제 질문은 : 쉬운 방법이 있습니까? 그렇다면 무엇입니까?

아무런 도움이되지 않습니다.

+4

[질문] [1]을 (를) 살펴보십시오. [1] : http://stackoverflow.com/questions/8538899/ –

+0

EF6에서 RemoveRange를 고려해 보셨습니까? 나는 그것이 "최적화"되고 실행되는 SQL이 얼마나되는지 알고 싶습니다. 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. 설치 엔티티 프레임 워크 확장 라이브러리 (PM> 설치 - 패키지 EntityFramework.Extended를) 코드에서

  2. 가져 오기 EntityFramework.Extensions

  3. 이 기록은 내부 쿼리에 의해 지정된 삭제

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

삭제 사용자 ID가 1 인 주문 내 모든 레코드가

+0

그렇기 때문에 EntityFramework가 특정 공급자 (SQL-Server)로만 제한된다는 정신 때문에 아닙니다. – springy76

5

일괄 삭제를하는 한 가지 방법은 외래 키에 ON CASCADE DELETE를 설정하는 것입니다. 디자이너에서 관계에 대해 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

관련 문제