2011-11-30 9 views
6

上の条件の選択は、私はこれらの簡素化EFはエンティティを生成していたと...Entity Frameworkの - 含まれるナビゲーションプロパティ

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

ビジネスロジック:

順序は、のための1つを複数のPOを持つことができます(ベンダはアイテムレベルで決定されます)。

子エンティティを選択的に含めることはできますか?

POを照会する際に、OrderとItemの子エンタを自動的に含める必要があります。

私は(インクルード使用して、これを実現する)...

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

これはそれが仕事だと背面関連企業を引っ張る、しかし、私はそのベンダーIDのベンダーIDと一致する項目エンティティを含めたいんPurchaseOrderエンティティ

従来のSQLでは、JOIN条件に含めるだけでしたが、EFは内部的にSQLを構築します。

エンティティ間に手動でJOINを作成せずに、どのLINQマジックを使って条件を適用することができますか?

答えて

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が今まで持っていた最も有益な機能の1つに悪くない... - – 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

拡張機能は、匿名型を動的に構築します。これは、@ 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)), 

}); 
関連する問題