Reputation: 8242
I'm using EF4.1 and trying to understand the proper approach to take for eager loading.
I have an order entry system with a Vendor (grandparent),Purchase Order (parent) and PO2Item (child) table. The model looks like this
I want to start with a PO2Item record and load the vendor. I thought I could just use .Include() like this:
var po = (from item in context.PO2Item.Include("PurchaseOrder.Vendor").AsNoTracking()
where item.OrderLineItemId == lineItem.CostSourceLineItemId
select item.PurchaseOrder).FirstOrDefault();
This does load the PurchaseOrder record but po.Vendor is null. I was reading Julia Lerman's book and Chapter 4 indicated I could use Load but I think 4.1 must have changed this from 4.0 because Load doesn't appear to be defined and there is no such thing as VendorReference. Eventually I dug into the ObjectContext and was able to do this:
if (po!=null)
{
context.GetObjectContext().LoadProperty(po, "Vendor");
}
which does load the Vendor but I have the feeling I'm missing something much simpler. Why doesn't Include("PurchaseOrder.Vendor") work?
Rather than cast the result as an ObjectQuery<> (a cool little trick by itself), I just wrote the query in two stages
var links = from link in context.PO2Item.Include("PurchaseOrder.Vendor").AsNoTracking()
where link.OrderLineItemId == lineItem.CostSourceLineItemId
select link;
var po_2_item = links.FirstOrDefault();
return po_2_item == null ? null : po_2_item.PurchaseOrder;
The returned PO (if one exists) now has the Vendor set properly.
Upvotes: 3
Views: 482
Reputation: 156524
I know this is already answered, but why not just do this?
// Get the purchase order (with Vendor) that has the given PO2Item
var po = context.PurchaseOrder.Include("Vendor").AsNoTracking().FirstOrDefault(
o => o.PO2Item.Any(i => i.OrderLineItemId == lineItem.CostSourceLineItemId));
Upvotes: 1
Reputation: 126547
.Include()
works on the shape of the returned query.
Your query returns a PurchaseOrder
, not a PO2Item
.
You need something more like (Guessing at the types here -- you may be using DbSet
-- adjust accordingly):
var po = ((ObjectQuery<PurchaseOrder>)
(from item in context.PO2Item
where item.OrderLineItemId == lineItem.CostSourceLineItemId
select item.PurchaseOrder))
.Include("Vendor")
.AsNoTracking()
.FirstOrDefault();
Upvotes: 2