7

假设我有这些简化的 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;}
}

商业逻辑:

一个订单可以有多个采购订单,订单上的每个不同供应商都有一个采购订单(供应商在项目级别确定)。

如何选择性地包含子实体?

在查询 PO 时,我想自动包含 Order 和 Item 的子实体。

我做到了这一点,使用 Include()...

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

这完成了它的工作并撤回了相关实体,但是,我只想包括其 VendorID 与 PurchaseOrder 实体的 VendorID 匹配的 Item 实体

对于传统的 SQL,我只是将其包含在 JOIN 条件中,但 EF 在内部构建它们。

我可以使用什么 LINQ 魔法告诉 EF 应用条件,而无需手动创建实体之间的 JOIN?

4

3 回答 3

4

你不能。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)
              };
于 2011-12-01T08:45:52.380 回答
4

您不能有选择地拉回符合特定条件的某些子实体。您能做的最好的事情就是自己手动过滤掉相关订单。

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);
         }
     }
}
于 2011-11-30T22:42:17.793 回答
1

您可以在这里使用 IQueryable-Extensions:

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

});
于 2013-07-04T09:34:18.693 回答