Selective Condition on Included Navigation Property in Entity Framework

c# entity-framework linq navigation-properties

Question

Assume I have these simplified EF generated entities...

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

Business Logic:

An order can have multiple POs, one for each distinct vendor on the order (vendors are determined at the Item level).

How Can I selectively Include Child Entities?

When querying for POs, I want to automatically include child entites for Order and Item.

I accomplish this, using Include()...

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

This does it's job and pulls back related entities, but, I only want to include Item entities whose VendorID matches the VendorID of the PurchaseOrder entity.

With traditional SQL, I'd just include that in the JOIN condition, but EF builds those internally.

What LINQ magic can I use tell EF to apply the condition, without manually creating the JOINs between the entities?

1
7
11/30/2011 10:32:56 PM

Accepted Answer

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);
         }
     }
}
4
11/30/2011 10:50:34 PM

Popular Answer

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


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow