Should we disable lazy loading of Entity Framework in web apps?

entity framework lazy loading not working
ef core disable lazy loading
entity framework eager loading
entity framework include
entity framework don't load related entities
lazy loading c#
proxycreationenabled vs lazyloadingenabled
ef core include vs join

I've heard that you have to disable the lazy loading feature of EF in web applications. (ASP.NET). Here and here, for instance.

Now I'm really confused because I always thought that lazy loading should always be enabled. So now my question is: is it really a better idea to disable lazy loading in web apps in terms of performance. If yes, could anyone explain the reasons and mention the pros and cons?

Avoid Lazy Loading Entities in ASP.NET Applications, On the opposite, disabling Lazy Loading means that you will have to manually handle each related property loading. Let's see how you can do  Disable Lazy Loading. In Entity Framework 4 and beyond Lazy Loading is enabled by default. We can disable it globally, on DbContext level, or selectively, on per-property level. To disable it globally you need to set the DbContext’s LazyLoadingEnabled property to false in the object’s constructor:

In web apps you have a lot of concurrent requests from different users, each request is being handled pretty fast (at least it should be), so you want to reduce number of DB calls during each request, because each DB request happens via network. With Lazy loading, every time you using relational property, it makes another call to DB to load this related data to your entity collection. So during one http request you can make a lot of additional requests to DB in such way, what from the performance prospective really hurts your application. In normal scenarios when you initially fetching your data from DB you already would know what related data do you need, so you can use eager loading of related entities to load everything that you need in one request to DB to handle particular http request.

Enable or disable LazyLoading in Entity Framework, Luckily, Entity Framework Core has made it harder to inadvertently turn it on. Let's see You can leverage Lazy Loading in a web app without doing it wrong. Lots of The fix here would be to simply add the eager loading. Disable Lazy Loading Lazy loading is enabled by default, but you can disable lazy loading for a particular entity or a context. Do not make a navigational property virtual, if you want to turn off lazy loading for a particular property. If you want to turn off lazy loading for all entities in the context, set its configuration property to false.

I had one legacy project. I was really surprised when I was checking in sql profile how many requests go to the database. It was about 180(!) for the home page! The home page has only two list with 20-30 items in each. So, you should understand N+1 requests very well. You should check carefully on code review it. For me, lazy loading gives a lot of problems. You never know how many requests go to the database when you use that feature.

Avoid Lazy Loading in ASP.NET, Disable Lazy Loading. We can disable lazy loading for a particular entity or a context. To turn off lazy loading for a particular property, do not make it virtual  You should turn lazy loading off in your web applications. TL;DR: Disable Lazy Loading in Web Apps. In EF Core the lazy loading feature isn’t even implemented yet, so if you’re already using EF Core, no need to worry about it. However, in EF 6 you can globally disable lazy loading in several ways. For just one query:

Lazy loading will create N+1 issue.

What does it mean?

It means that it will hit the DB once (at least) for each object loaded + the initial query.

Why is it bad?

Suppose you have these classes Movie and MovieGenre, and you have 100 movies with 30 genres between them in the DB

public class Movie
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public virtual MovieGenre MovieGenre { get; set; }

        public byte MovieGenreId { get; set; }
}

public class MovieGenre
    {
        public byte Id { get; set; }

        public string Name { get; set; }
    }

Now suppose you are navigating to a page that will show all the 100 movies (remember the 30 movie genres?), the db will execute 31 queries (30 for each movie genre + 1 for movies) and the queries will be something like this

Initial query (+1 part):

SELECT Id, Name, MovieGenreId
From Movie

Additional queries (N part): -- 1 SELECT Id, Name From MovieGenre Where Id = 1

-- 2
SELECT Id, Name
From MovieGenre
Where Id = 2

-- 3
SELECT Id, Name
From MovieGenre
Where Id = 3

-- 4
SELECT Id, Name
From MovieGenre
Where Id = 4
.
.
.

Eager loading avoids all this mess and will use one query with the correct joins.

since you are using C# here is a tool called glimpse that you might want to use to understand the issue further.

Lazyloading in Entity Framework, How does Entity Framework load the data if Lazy Loading is disabled? Disable the lazy loading will not cause the framework auto-loading In a web app, with lazy loading disabled (or not enabled in EF Core), you will  There are options to disable Lazy Loading in an Entity Framework. After turning Lazy Loading off, you can still load the entities by explicitly calling the Load method for the related entities. There are two ways to use Load method Reference (to load single navigation property) and Collection (to load collections), as shown below.

I think you need to start by asking few questions, before choosing one and rejecting other way:

  1. How big is my data set and do I need related data immediately? (This again is specific to your need)
  2. As other people have already told about N+1 issue; however, this becomes important depending on size of your dataset.
  3. Will it be pragmatic to have a round-trip to server to fetch related data?
  4. Then there is need of data. Whether you want it realtime or cached version will do?

My contribution to all important inputs by others.

Lazy Loading, Entity Framework defaults to lazy loading and allows you to override it eager loading (more data) will give you better performance than lazy  Turn Off Lazy Loading. Lazy loading and serialization don’t mix well, and if you aren’t careful you can end up querying for your entire database just because lazy loading is enabled. It’s a good practice to turn lazy loading off before you serialize an entity. Turning Off for Specific Navigation Properties

Best Practices for Lazy Loading in Entity Framework -- Visual Studio , The Contoso University sample web application demonstrates how to create ASP .NET MVC 5 applications using the Entity Framework 6 Code First and Visual Studio. You specify eager loading by using the Include method. The lazy loading and explicit loading examples would both result in eleven  We can disable lazy loading for a particular entity or a context. To turn off lazy loading for a particular property, do not make it virtual. To turn off lazy loading for all entities in the context, set its configuration property to false.

Tutorial: Read related data with EF in an ASP.NET MVC app , There are several ways that the Entity Framework can load related data into the In a web application, lazy loading may be of relatively little value anyway, because You can disable it when you instantiate an object context. I was following a tutorial from Pluralsight called "Building Web Apps & Services with Entity Framework and Web API". I followed the tutorial but started getting errors when trying to return my entity framework objects. The objects had been set up with lazy loading. I have two kinds of objects - Projects and ProjectTasks.

Maximizing Performance with the Entity Framework 4.0 in an ASP , This week's tip is on the topic of lazy loading using Entity Framework or EF Core NET Core apps. I recommend disabling lazy loading in all ASP. On any given web request, the goal should be to return a response to the  One small, but important point. Use of Include() is eager loading. Getting EF to load entities as and when they are needed is lazy loading. You want to disable lazy loading, so that you can test eager loading - the correct use of Include().

Comments
  • I believe that lazy loading introduces one more query to DB, instead of just one. So you can load all the data in one query using Include(), for example. Also if you use same entities in your API controllers in output positions, serializer will always traverse the whole object to serialize it completely what, in order, will call lazy loading on that entity.
  • The examples aren't convincing at all. They show code that should never be lazy loading, period. Whether it's in a web app or in a stateful client, the n + 1 query pattern should always be avoided. Maybe your question isn't opinion-based. If you can show me a case where you absolutely need lazy loading then yes, you need lazy loading, no discussion. Until then the only answer is: it depends. I.e. opinion-based, or broad, or unclear, whatever, but not a good fit on Stack Overflow.
  • Your argument makes sense, but what confuses me here is that let's say we have some product categories in our system, and with every HTTP request, we have to fetch all these categories from the database, if we have disabled the lazy loading, when we fetch a category, all of its related products would be fetched too, since we have to fetch all categories, we actually fetch all the products in our database! And it'll be worse if we have some related entities to products, such as its "Brand". So based on this approach, in fact, we're fetching the entire database for each request, is that OK?
  • If you fetch entire database for each request, it means that you need entire database for each request - which is strange. In general of course you would need to separate your repository methods which brings some complexity, for example instead of one fetching method GetUsers (with Lazy Loading on you can further download all related data) you will end up with something like GetUsersWithPurchases and GetUsersWithSettings and so on. So for each particular use case you would need separate fetching logic. You shouldn't use one method that loads everything for every use case.
  • @AmirArbabian No, I do not need the entire database for each request, I said my scenario, I think you've misunderstood it, I said imagine you have an entity that lives in the database, and for each request, you need to fetch it from the database, without lazy loading, when you fetch that entity from the database, you're actually fetching all its related entities, and the related entities of each related entity again, and eventually you end up with the entire database in the memory. I hope I made myself clear...
  • @AmirHosseinAhmadi but if you need this entity with all it's relations that means you anyway will load all of that, but doing that via Lazy Loading you will do few request to database instead of one.
  • @AmirHosseinAhmadi, I use T-SQL. Every junior developer can write SQL requests. Or I can teach it for a couple of weeks. It is simpler. Everybody understands what's going on. I have two approaches. If a SQL request is without joins, I use ORM. Or if need to insert a big complex entity, I use ORM. This case is easier to use ORM. But I prefer SQL if I need complex SQL request with one or many joins.
  • I understand what you're saying. But the question I have here is that for example let's say I want to fetch the data of a single genre, and that genre has 10,000 related movies. With eager loading, if I fetch that single genre, all the data of its 10,000 movies are also fetched. Isn't that an issue?
  • if you fetch all the genres movies aren't fetched unless you specifically ask for it. why? because Movie class is referencing MovieGenre not the other way around
  • In my EF class in the MovieGenre class I have a public List<Movie> Movies { get; set; }. Isn't that fetched every time I fetch a genre?
  • why would you have a list inside the model? it indicates that you do have a many to many relationship. Still not clear for me what is the issue here?
  • I think the only way to answer your question is to try glimpse on your application and it will show you something like this