2011-11-30 10 views
6

Przyjmijmy, mam te uproszczone EF generowane podmioty ...Entity Framework - Selektywne Stan na zestawie nawigacji obiekt

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;} 
} 

firm logicznych:

Zamówienie może mieć wiele OP, jeden dla każdy odrębny dostawca na zamówienie (dostawcy są określani na poziomie przedmiotu).

Jak selektywnie uwzględnić jednostki podrzędne?

Podczas wysyłania zapytań o zamówienia, chcę automatycznie dołączyć dziecko do zamówienia i przedmiotu.

to osiągnąć za pomocą include() ...

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

To nie jest praca i ciągnie podmiotów związanych z powrotem, ale Chcę tylko obejmują podmioty elementu, którego VendorID dopasowuje VendorID z następujących Jednostka PurchaseOrder.

W tradycyjnym SQL, po prostu uwzględniłbym to w warunku JOIN, ale EF tworzy je wewnętrznie.

Jakiej magii LINQ można użyć, powiedz EF, aby zastosować warunek, bez ręcznego tworzenia powiązań między obiektami?

Odpowiedz

2

Nie można selektywnie wycofać niektórych obiektów podrzędnych, które pasują do określonego warunku. Najlepsze, co możesz zrobić, to samodzielnie odfiltrować odpowiednie zamówienia.

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

Mam nadzieję, że to jako wzmocnienie funkcji w przyszłości. – ctorx

+0

@Matthew - byłyby świetnym dodatkiem do struktury –

+0

więcej niż pięć lat i wciąż nic ... zadziwiające, niezłe z powodu jednej z najbardziej przydatnych funkcji EF może kiedykolwiek ... -.- ' – Shockwaver

3

Nie możesz. EF nie zezwala na warunki do szybkiego ładowania. Musisz użyć wielu zapytań jak:

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; 

Albo można użyć projekcji w jednym zapytaniu:

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

można użyć IQueryable-extensions tutaj:

https://github.com/thiscode/DynamicSelectExtensions

Rozszerzenie buduje dynamicznie anonimowy typ. Będzie to użyte do projekcji, jak opisuje @ Ladislav-Mrnka.

Następnie można to zrobić:

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)), 

}); 
Powiązane problemy