Lazy Loading Entities in EntityFramework

In my previous blog posting we learned how to eagerly load entities in entity framework. Eager loading causes lots of entities to be loaded ahead of time which may not be required and feasible in all scenarios. In those cases you can call Load Method on an entity or collection of entities to lazy load entities on demand. This ensures that you do not bring lots of data from database and only loading entities when you need them. The problem with this approach is, your querying process would be very chatty and you would end up making too many database calls. For example if you have collection of customers and you want to lazy load customer's address, than depending on the number of customers you have in your collection, linq to entities will make that many number of calls to get addresses for all customers in the list.

So we basically covered two scenarios. The first scenario where you want to eagerly load entities such as Orders for customer, second scenario where you lazy load addresses for a customer only when you need them. What if you have a situation that comes in a middle where you want to lazy load an immediate collection but when you lazy load the immediate collection, you want to eagerly load its nested collection.  For example you want to lazy load Orders for a customer but when you are loading the Orders, you want to immediately Load all the OrderDetails for those Orders. In a situation like this, you can get a reference to CreateSourceQuery method on the lazy loaded child collection. CreateSourceQuery method contains the query which would be sent to fetch that particular lazy loaded entity. Since CreateSourceQuery returns an ObjectQuery, you can call Include method to specify additional sub collections that you want loaded with the lazy loaded collections.

In the example below,I am lazy loading Orders for a customer. For each Order, I am eagerly fetching its OrderDetails.

image

In the above example, I could have called cust.Orders.Load to lazy load my Orders for the customer. However this would not give me an opportunity to load its OrderDetails. To ensure I can load my OrderDetails along with the Order, I am getting a reference to CreateSourceQuery method on the Orders collection and than appending my includes that tells what other tables include when loading the Orders Collection. In the case of CustomerDemographics, I had no need for loading additional tables, so I am making use of the Load option to tell entity framework to load CustomerDemographics entities. If I do not call Load, you do not get any errors but the collection count returns a value of 0. One could argue that collection count of 0 means customer did not have any demographics but in this case they do have a value of 1. The way you can differentiate between a true value of 0 and 0 being not loaded is by checking the IsLoaded property on a collection to see if the collection was loaded from the database or not.

No Comments