[英]Entity Framework - Selective Condition on Included Navigation Property
假設我有這些簡化的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,一個用於訂單上的每個不同供應商(供應商在物料級別確定)。
我如何選擇性地包括兒童實體?
查詢PO時,我想自動為訂單和項目添加子項目。
我完成了這個,使用Include()...
Context.PurchaseOrders.Include("Orders.Items");
這是它的工作並拉回相關實體,但是, 我只想包含其VendorID與PurchaseOrder實體的VendorID匹配的Item實體 。
對於傳統的SQL,我只是在JOIN條件中包含它,但EF在內部構建它們。
我可以使用什么LINQ魔術告訴EF應用條件,而無需在實體之間手動創建JOIN?
您無法有選擇地撤回符合特定條件的某些子實體。 您可以做的最好的事情是自己手動過濾相關訂單。
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);
}
}
}
你不能。 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-Extensions:
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)),
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.