Background
This is the eight part of the Entity Framework 4 learning series. I’ll be demonstrating the technique called Lazy Loading or what is also called as Deferred Loading using Entity Framework. Lazy loading is a term used to load dependent objects. This concept is not just applicable to ORM but even other concepts like Dependency Injection frameworks use it. The dependency injection containers which I have used like Spring.Net, Castle Windsor etc offer this facility. In the ORM world NHibernate supports lazy loading. The idea behind lazy loading is you defer the loading of objects until they are required by the runtime objects.
Pre-requisite
Like earlier post we’ll have to have the entity data model ready using the Northwind database schema. Please refer to my earlier post if you are not ware how to build the entity data model based on existing database objects.
Simple example of Lazy Loading
Lets write a simple query to fetch the top 20 employees from the Northwind database and count the number of orders placed by each employee.
NORTHWNDEntities context = new NORTHWNDEntities();
var employees = context.Employees.Take(20).ToList();
foreach (Employee employee in employees)
{
Console.WriteLine("Total number of order by employee : {0}", employee.Orders.Count);
}
We start off with creating the ObjectContext which is NORTHWNDEntities in our case. We filter the 20 employees using Take method on the employees entity collection. Then we loop over the individual employees and display the count of Orders to the console window.
By default Entity Framework 4 enables the Lazy Loading feature. Because of this there are multiple hits to the database server. The initial query which filters the 20 employees is executed when we start iterating over the loop. And then for each employee a separate query is executed within the foreach loop.
Turn-off Lazy Loading
We can turn off the lazy loading feature and fetch the related records in one query itself. This process is termed as eager loading. To turn off Lazy Loading we can set LazyLoadingEnabled property of the ContextOptions on context to false.
context.ContextOptions.LazyLoadingEnabled = false;
Now if we run the earlier code, we get the count of orders as 0. This is because only the first query is executed.
Explicitly Include results
If we want the resultset to include the dependent records we need do explicitly tell the framework to include them along with the first query results.
var employees = context.Employees.Include("Orders").Take(20);
Use the Load Method to request for related records
Another alternative is to call the load method inside the loop to load the related records.
employee.Orders.Load();
Console.WriteLine("Total number of order by employee : {0}", employee.Orders.Count);
Please note that in this case we should not use the Include method mentioned earlier on the statement which filters the 20 employees. We would run the query similar to the first case and then use the load method to load related objects.
Conclusion
Lazy loading is helpful if we have a large object graph and we need to perform some in memory calculations one at a time. We should be careful while using Lazy loading with service layer. Since services use serialization to transfer data over the wire, lazy loading might increase the processing time during serialization. In such scenarios we should avoid using lazy loading.
As usual I have uploaded the complete working solution to dropbox which can be downloaded here.
Unit next time Happy Programming :)
Further Reading
Here are some books I recommend related to the topics in this post.
nice post
ReplyDeleteI like the post, I was searching for Lazy Loading and got my doubts clear from this post. The language is simple to understand .
ReplyDeleteThanks
Nilesh
Very Nice, good job. When to use Load and when to use Include?
ReplyDeleteNicely explained.. good job
ReplyDeletegood Job.. Nicely explained
ReplyDeleteNicely explained.. good job
ReplyDeleteGood job,
ReplyDeleteBut why in my code I cant write Include like lambda expresion but just a string :
var employees = context.Employees.Include(e=> e.Orders).Take(20);
what I have to reference in my project to use in this way?
@ gazmend mehmeti : check for = > using System.Data.Entity; to be included in the page
ReplyDelete@ gazmend : use = > using System.Data.Entity;
ReplyDelete