2011-11-30 4 views
6

내가 가지고 이러한 단순화 된 EF 생성 된 개체를 가정 탐색 속성을 포함 선택적 조건 ...엔티티 프레임 워크 -

public class PurchaseOrder 
{ 
    public int POID {get;set;} 
    public int OrderID {get;set;} 
    public int VendorID {get;set;} 
    public IEnumerable<Order> Orders {get;set;} 
} 

public class Order 
{ 
    public int OrderID {get;set;} 
    public decimal Price {get;set;} 
    public IEnumerable<Item> Items {get;set;} 
} 

public class Item 
{ 
    public int OrderID {get; set;} 
    public string SKU {get;set;} 
    public int VendorID {get;set;} 
    public Order Order {get;set;} 
} 

비즈니스 로직 :

를 들어, 하나를 다른 POS를 취득 할 수있는 순서 주문의 각 개별 공급 업체 (공급 업체는 품목 수준에서 결정됨)

하위 엔티티를 선택적으로 포함 할 수 있습니까?

PO를 쿼리 할 때 주문 및 항목에 대한 하위 항목을 자동으로 포함하고자합니다.

나는

Context.PurchaseOrders.Include("Orders.Items"); 

이 그것을 가 난 단지 항목 엔티티 그 VendorID 값이의 VendorID 값과 일치를 포함하려면, 직업 다시 관련 개체를 가져옵니다,하지만 않습니다 ...) (포함하여,이를 PurchaseOrder 엔터티.

기존의 SQL에서는 JOIN 조건에 포함 시켰지만 EF는 내부적으로 SQL을 작성했습니다.

어떤 LINQ 매직을 사용하여 엔티티간에 수동으로 JOIN을 작성하지 않고도 EF에 조건을 적용 해 줄 것을 말할 수 있습니까?

답변

2

특정 조건과 일치하는 특정 하위 항목을 선택적으로 되돌릴 수 없습니다. 자신이 직접 할 수있는 최선의 방법은 관련 주문을 직접 필터링하는 것입니다.

public class PurchaseOrder 
{ 
    public int POID {get;set;} 
    public int OrderID {get;set;} 
    public int VendorID {get;set;} 
    public IEnumerable<Order> Orders {get;set;} 

    public IEnumerable<Order> MatchingOrders { 
     get { 
      return this.Orders.Where(o => o.VendorId == this.VendorId); 
     } 
    } 
} 
+0

나는 미래의 기능 향상으로 이것을 볼 수 있도록 노력하겠습니다. – ctorx

+0

@Matthew - 그들은 프레임 워크 –

+0

에 5 년 이상 훌륭한 요소가 될 것이며 아직 아무것도 아는 것이 없다 ... 놀라운 점은 EF가 가질 수있는 가장 유용한 기능 중 하나인데 ... - – Shockwaver

3

수 없습니다. EF는 열심히로드하는 조건을 허용하지 않습니다. 당신처럼 여러 쿼리를 사용하여 다음 중 하나 여야합니다

var pos = from p in context.PurchaseOrders.Include("Order") 
      where ... 
      select p; 
var items = from i in context.Items 
      join o in context.Orders on new { i.OrderId, i.VendorId} 
       equals new { o.OrderId, o.PurchaseOrder.VendorId } 
      where // same condition for PurchaseOrders 
      select i; 

또는 당신은 단일 쿼리에 프로젝션을 사용할 수 있습니다

var data = from o in context.Orders 
      where ... 
      select new 
       { 
        Order = o, 
        PurchaseOrder = o.PurchaseOrder, 
        Items = o.Items.Where(i => i.VendorId == o.PurchaseOrder.VendorId) 
       }; 
1

당신은 여기에 IQueryable-확장을 사용할 수

https://github.com/thiscode/DynamicSelectExtensions

Extension은 익명 형식을 동적으로 작성합니다. 이것은 @ Ladislav-Mrnka에 의해 묘사 된 것처럼 투영에 사용될 것입니다.

그럼 당신은이 작업을 수행 할 수 있습니다

var query = query.SelectIncluding(new List<Expression<Func<T,object>>>>(){ 

//Example how to retrieve only the newest history entry 
x => x.HistoryEntries.OrderByDescending(x => x.Timestamp).Take(1), 

//Example how to order related entities 
x => x.OtherEntities.OrderBy(y => y.Something).ThenBy(y => y.SomeOtherThing), 

//Example how to retrieve entities one level deeper 
x => x.CollectionWithRelations.Select(x => x.EntityCollectionOnSecondLevel), 

//Of course you can order or subquery the deeper level 
//Here you should use SelectMany, to flatten the query 
x => x.CollectionWithRelations.SelectMany(x => x.EntityCollectionOnSecondLevel.OrderBy(y => y.Something).ThenBy(y => y.SomeOtherThing)), 

});