New Posts New Posts RSS Feed: Include paths work even with collection-returning properties
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Include paths work even with collection-returning properties

 Post Reply Post Reply
Author
WardBell View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 31-Mar-2009
Location: Emeryville, CA,
Posts: 338
Post Options Post Options   Quote WardBell Quote  Post ReplyReply Direct Link To This Post Topic: Include paths work even with collection-returning properties
    Posted: 17-Apr-2009 at 2:19pm

I want to talk about how INCLUDE works with navigation properties (aka, "relation properties") that return collections. The INCLUDE syntax may surprise you ... as it did me.

But first, an introduction to the INCLUDE keyword.
All of this is described in our documentation, btw. I'm just explaining it in a different terms.
When you query for one kind of object, you may want to get some of the related objects at the same time in the same trip to the data source. You can do this by adding an advisory to the LINQ query that is known as a "span". In DevForce and Entity Framework, you specify the span with the INCLUDE keyword.
 
Let's say you have a query for Orders:
MyManager.Orders.Where(...).ToList();
You want to retrieve the Customers of those Orders at the same time; you write:
MyManager.Orders.Where(...).Include("Customer").ToList();
The syntax calls for you to supply the name of the navigation property that you would use to traverse from an instance of the retrieved type (Order) to an instance of the related type.  We're mentioning the "Customer" property in our example.
I'm not to thrilled about the use of the string. I prefer something strongly typed so I can guard against changes to property names. But this is the way Entity Framework does it so we'll play along.
 
DevForce offers a mechanism to free you from strings, at least in the simple cases. It's called "PathFor" and you'll find it described in our documentation. In our example, we could write ... Include(Customer.PathFor(c=>c.Customer))...
 
Not loving it? Me neither.
That query statement returns the selected Orders and simultaneously retrieves the Customers for those Orders.
 
Those Customers are not actually in the result of the query ... the query result consists only of Orders ... but they are waiting for you in the entity cache. Which means if you ask for the Customer associated with one of the selected Orders (e.g., anOrder.Customer), DevForce finds the Customer in cache and doesn't have to make a separate, expensive trip to the database.
 
This is known as "eager fetching" and it's a good thing when you know you're going to need the related entities. The downside is that the SQL query can get unwieldy and slow AND you'll be sending a lot more data over the wire. So be careful and test what you're doing.
 
You can have multiple Include specifications as in:
MyManager.Orders.Where(...)
  .Include("Customer")
  .Include("Shipper")
  .Include("OrderDetails")
  .ToList();
Pretty cool, eh? But watch out! The SQL here will have many JOINs and, if it even finishes before the timeout, you'll have pulled across many megs of data.
 
You can also specify a path in the Include as in:
MyManager.Orders.Where(...)
  .Include("Customer.Address")
  .Include("Shipper")
  .Include("OrderDetails")
  .ToList();
This will fetch the Customers of the seleced Orders and the Addresses of those Customers as well as the Shippers and OrderDetails. 
I am pretending that Customer has a related Address navigation property.
Now for the surprise ... and the point of this post.
 
Suppose I want to eagerly fetch the Products of the OrderDetails?
 
The following expression is illegal and nonsensical: anOrder.OrderDetails.Product
 
The OrderDetail entity does have a Product navigation property. But anOrder.OrderDetails returns a collection ... and there is no Product property on that collection.
 
Are we stuck? Or can we we get the OrderDetails and Products related to our selected Orders?
 
We can:
MyManager.Orders.Where(...)
   .Include("OrderDetails.Product")
   .ToList();
Apparently the Include's string parameter describes a path without regard to whether the named navigation properties return one or many entities.
 
That's ok with me.
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down