Automatic entityset mapping in Entity Framework

As I am starting to do work on both linq to SQL and linq to entities, I am finding lots of subtle differences on both implementations. Some implementations I would consider as being better over the other.

In Linq to SQL, if I have a customer object and want to get access to its orders collection, all I simply have to do is navigate to the Orders collection property and linq to SQL lazy loads the orders for that particular customer instance. But what happens if I already have orders in the memory and some of the orders do actually belong to the customer that is loaded. Although using primary keys, linq to SQL can associate those orders to the customer based on the mapping definition but it will not do so. However in entity framework, if you have loaded some orders from the database randomly based on some criteria and if there is a customer in memory whose orders are part of that randomly selected orders, than entity framework would automatically associate those orders to that customer with out you making a request for the Orders for that customer. It could be considered a plus and minus point. Plus because it automatically uses the associations of the customer with orders based on entity key to tie those orders to that customer. The minus is because those subset of orders in memory may not represent all the orders for that customer and that could be very confusing and hard to debug problems when the Orders Collection does not show all the orders for the customer. Here is an example that illustrates this issue.

image

image 

In the above example, I am turning off deferred loading on linq to SQL datacontext. The reason I am doing is because when I apply the count operator on the Orders collection, I don’t want linq to SQL to go and fetch the orders for the customer instance.  In the linq to SQL portion of the code, I am first retrieving all the orders in the database and loading it up in the memory. I then go ahead and retrieve the ALFKI customer from the database and print its Orders. Based on the results on the output window of 0, you can surmise that linq to SQL did not associate the orders in the tracking service with customer based on the primary key value.

Next portion of my code does the same thing except using entity framework. I first retrieve the customer and than I am retrieving all the orders for the employee id of 4. Next I am printing the Orders for the ALFKI customer. By default we would expect a value of 0 based on how entity framework is implemented because in entity framework the child collections do not get loaded until you call Load method. However we still see 2 in the output window.  The reason is, the orders we loaded earlier based on employeeid of 4, has 2 orders that belong to ALFKI customer. This result is misleading because there are actually 6 orders of ALFKI customer but only 2 of them are loaded in memory.

1 Comment

  • Two main comments here:

    1) The EF provides the IsLoaded property on EntityCollection and on EntityReference which can be used to determine if the relationship is entirely loaded or not. So in your case above, even though there are some orders in the customer's orders collection, the IsLoaded property on that collection will be false making it fairly easy to determine that you can't count on the contents of that collection as being the full set of related entities. If you do need to know the full set, you can always just add something like this:

    if (cust1.Orders.IsLoaded == false)
    {
    cust1.Orders.Load();
    }

    before you take the count.

    2) The EF behavior which is causing these associations to appear is something we call "relationship span" where relationship info is retrieved by default for entity reference relationships when entities are retrieved in the context. That information is then used to "fixup" relationships if the appropriate entity is already or later is added to the context. You can read more about this on my blog at:

    http://blogs.msdn.com/dsimmons/archive/2007/12/21/filtered-association-loading-and-re-creating-an-entity-graph-across-a-web-service-boundary.aspx

    - Danny

Comments have been disabled for this content.