Welcome everyone to a new post in the Entity Framework Core course! Today, we'll look at the different options Entity Framework Core provides for loading related data, depending on your application's needs.
Table of Contents
Remember, all this code is available on GitHub. Before continuing with this post, I recommend checking out the one about relationships in Entity Framework Core.
1 - What is Eager Loading in Entity Framework Core
Even though we haven’t talked directly about what Eager Loading is, we have seen it indirectly. Eager Loading consists of directly loading the data related to your entity in the same query as the main entity.
In Entity Framework Core, you can do this when using dbSet
with .Include()
:
[HttpGet("eager-loading")]public async Task<List<User>> EagerLoading() => await _context.Users .Include(a => a.Wokringexperiences) .ToListAsync();
In this scenario, when loading users, we're including their working experiences in the same query, which in SQL translates to a join.
2 - What is Lazy Loading in Entity Framework Core
We also touched on lazy loading or deferred loading before when I explained IQueryable. Here’s when you load a main entity, but the related data isn’t loaded until you access the property on the entity.
Before making changes to your code, keep in mind that since .NET Core 3, you have to install the Microsoft.EntityFrameworkCore.Proxies
package in your project, since it’s not included by default.
In the options, when including the DBContext
, you must specify the following configuration:
services.AddDbContext<CursoEfContext>(options=> options .UseLazyLoadingProxies() // <----- HERE .UseMySQL("server=127.0.0.1;port=4306;database=cursoEF;user=root;password=cursoEFpass"));
And finally, in the entity, it should be declared as virtual:
public virtual ICollection<Wokringexperience> Wokringexperiences { get; set; }
Now we can go into the logic itself. In our case, we change the code to the following, and the part where we query working experiences won’t execute until you reach the line that accesses it:
[HttpGet("lazy-loading/{userId}")]public async Task<User?> LazyLoading(int userId){ User? user = await _context.Users.FirstOrDefaultAsync(a => a.Id == userId); if (user is not null) { var experiences = user.Wokringexperiences; // <---- HERE if (experiences is not null && experiences.Any()) { Console.WriteLine("this user has experiences"); } } return user;}
At first, this solution seems the best, but be careful—one query with a join, even if it has a lot of records, is very likely to be faster than many small queries. So, depending on what you want or are doing, you’ll need to choose wisely between Eager Loading and Lazy Loading.
These are the queries executed from the previous code:
- Note: Do not confuse Lazy Loading in Entity Framework Core with
Lazy<T>
in .NET.
3 - Explicit Loading in Entity Framework Core
Finally, when we use explicit loading, it's very similar to lazy loading. We don’t load the data automatically; instead, we must specify it explicitly.
For example, if we load a user, and want to load their workingExperiences
, we do it like this:
[HttpGet("explicit-loading/{userId}")]public async Task<User?> ExplicitLoading(int userId){ User? user = await _context.Users.FirstOrDefaultAsync(a => a.Id == userId); if (user is not null) { await _context.Entry(user) .Collection(a => a.Wokringexperiences) .LoadAsync(); // <----- HERE if (user.Wokringexperiences is not null && user.Wokringexperiences.Any()) { Console.WriteLine("this user has experiences"); } } return user;}
As you can see, we're specifying the collection and then loading the data using the Load()
/ LoadAsync()
method. Just like in lazy loading, it is done with a separate query.
One thing to keep in mind is that explicit loading can be used even when lazy loading is disabled (or the proxy isn’t enabled), so it can serve as a hack in some scenarios.
Conclusion
As with everything in software development, the choice between Lazy Loading, Eager Loading, and Explicit Loading will depend on your specific situation and requirements. I hope this post helps you make the best decision!
If there is any problem you can add a comment bellow or contact me in the website's contact form