Lazy Loading

by Sachin Singh


Posted on Saturday, 06 February 2021

Tags: Lazy Loading in Entity Framework with Linq

By default related objects are not loaded immediately , they are loaded on demand when we access them.

Blog Database diagram
Blog Database Diagram

Carefully observe the relationship between tables shown below.
  1. Category and Post:- have a one-to-many relationship. This means there can be several Posts in the same category.
  2. Post and comments:- have a one-to-many relationship, which means there can be many comments on a Post.
  3. User and Comment :- have a one-to-many relationship , means a user may post several comments on a Post .

Example 1. Fetch number of posts in each category.


    public class Program
    {
        public static void Main()
        {
            var db = new BlogDbContext();
            var categories = db.Categories.ToList();
            foreach(var cat in categories)
            {
                Console.WriteLine("Category :{0} | Number of Posts :{1}", cat.CategoryName,cat.Posts.Count());
            }
            Console.ReadLine();
        }
   }

In the above example we are first loading all the categories into the memory using the ToList() method which causes immediate execution, but even with the immediate execution we couldn't load the related objects , means db.categories.ToList() query only loads the category objects into the memory and not the related post objects.

When we iterate over the query variable and fetch any property the related object then only the linq provider fires the necessary T-SQL to the database and loads the related object into the memory, in our case cat.Posts.Count() statement loads the post object (count) into the memory.

Output:

Output
output

N+1 Issue

Lazy loading causes n+1 issue , means to get N entities and their related entities you will end up with n+1 query requests to the database. The diagram shown below explains it in more details.

N+1 issue
N+1 Issue

How does Lazy loading work behind the scene?

When we generate entity then for any type of relationship, corresponding navigation properties are also created , when you look closely you will find all navigation properties are marked as virtual , see below entities generated by Entity Framework.

Lazy Loading behind the scene
Lazy loading behind the scene

If you have a little knowledge about OOPs polymorphism concept then you would know that virtual keyword is used to achieve run time polymorphism means we can change the behavior of a method / property at run time by simply overriding them. The same concept is being applied here , at run time the navigation properties change their behavior something like shown below.

Lazy Loading behind the scene1
Lazy loading behind the scene overriding

So , with each iteration a new request goes to the server to load the related entities , which results in too many requests and degrade the performance, so don't use Lazy loading until you really need it.

How to disable Lazy loading

Lazy loading is by default enabled, in order to disable it you have two options.
  1. Delete the virtual keyword from navigation properties.
  2. Disable it for the whole project by configuring it in the DbContext as shown below.

Disable Lazy Loading
Disable Lazy loading