C# 实体框架-包含的导航属性的选择条件
假设我有这些简化的EF生成实体…C# 实体框架-包含的导航属性的选择条件,c#,linq,entity-framework,navigation-properties,C#,Linq,Entity Framework,Navigation Properties,假设我有这些简化的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 OrderI
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;}
}
这就完成了它的工作,并收回相关的实体,但是,我只想包括其VendorID与PurchaseOrder实体的VendorID匹配的项目实体
对于传统的SQL,我只是将其包含在连接条件中,但EF在内部构建这些条件
我可以使用什么LINQ magic来告诉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 IEnumerable<Order> MatchingOrders {
get {
return this.Orders.Where(o => o.VendorId == this.VendorId);
}
}
}
公共类采购订单
{
公共int点{get;set;}
公共int-OrderID{get;set;}
public int VendorID{get;set;}
公共IEnumerable命令{get;set;}
公共IEnumerable匹配顺序{
得到{
返回this.Orders.Where(o=>o.VendorId==this.VendorId);
}
}
}
你不能。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)
};
您可以在此处使用IQueryable扩展: 扩展动态构建匿名类型。这将用于@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)),
});
var query=query.selectinclude(新列表>(){
//示例如何仅检索最新的历史记录条目
x=>x.HistoryEntries.OrderByDescending(x=>x.Timestamp).Take(1),
//如何对相关实体进行排序的示例
x=>x.OtherEntities.OrderBy(y=>y.Something)。然后by(y=>y.Something),
//示例如何检索更深一层的实体
x=>x.CollectionWithRelations.Select(x=>x.EntityCollectionsSecondLevel),
//当然,您可以对更深层次进行排序或子查询
//在这里,您应该使用SelectMany来展开查询
x=>x.CollectionWithRelations.SelectMany(x=>x.EntityCollectionsSecondLevel.OrderBy(y=>y.Something)。然后通过(y=>y.Something)),
});
我希望在未来将此视为一项功能增强。五年多了,但仍然一无所获。。。令人惊讶的是,对于EF可能拥有的最有用的功能之一来说,这并不坏
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)),
});