Entity Framework - Selective Condition on Included Navigation Property

前端 未结 3 1755
花落未央
花落未央 2020-12-20 18:22

Assume I have these simplified EF generated entities...

public class PurchaseOrder
{
     public int POID {get;set;}
     public int OrderID         


        
相关标签:
3条回答
  • 2020-12-20 18:56

    You can't. EF doesn't allow conditions for eager loading. You must either use multiple queries like:

    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;
    

    Or you can use projection in single query:

    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)
                  };
    
    0 讨论(0)
  • 2020-12-20 18:58

    You can't selectively pull back certain child entities that match a certain condition. The best you can do is manually filter out the relevant orders yourself.

    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 讨论(0)
  • 2020-12-20 19:07

    You could use the IQueryable-Extensions here:

    https://github.com/thiscode/DynamicSelectExtensions

    The Extension builds dynamically an anonymous type. This will be used for projection as described by @Ladislav-Mrnka.

    Then you can do this:

    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)),
    
    });
    
    0 讨论(0)
自定义标题
段落格式
字体
字号
代码语言
提交回复
热议问题