Welcome everyone to a new post in the Entity Framework Core course, where today we're going to explore the different options available in Entity Framework Core for loading related data, depending on your application's needs.
Table of Contents
Remember that all this code is available on GitHub. Before you continue with this post, I recommend checking out the one about relationships in Entity Framework Core.
1 - What is Eager Loading in Entity Framework Core
Although we haven’t looked directly at what Eager Loading is, we’ve actually seen it indirectly. Eager Loading simply means loading all related data of your entity in the same query as the main entity.
In Entity Framework Core, this is achieved when we use dbSet
with an .Include()
:
[HttpGet("eager-loading")]
public async Task<List<User>> EagerLoading()
=> await _context.Users
.Include(a => a.Wokringexperiences)
.ToListAsync();
In this scenario, when we load the user, we’re also including the working experiences in the same query, which translates to a join in SQL.
2 - What is Lazy Loading in Entity Framework Core
Lazy Loading is something we also covered briefly when I explained IQueryable. This is when we load a main entity, but the related data is not retrieved until we actually access that property of the entity.
Before making changes to the code, keep in mind that since .NET Core 3, you need to install the Microsoft.EntityFrameworkCore.Proxies
package in your project, because it's no longer included by default.
When configuring the DBContext
, you need to specify the following settings:
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, mark it as virtual:
public virtual ICollection<Wokringexperience> Wokringexperiences { get; set; }
Now, we can go to the logic itself. In our case, we change the code as shown below, and the part where we request the working experiences won’t execute until we reach the line where we access them:
[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 glance, this solution may seem the best, but be careful: a query with a join, even with lots of records, can often be much faster than many small queries. So, depending on what you want or what you're doing, you’ll need to use your best judgment when choosing between Eager Loading and Lazy Loading.
These are the queries that execute from the previous code:
- Note: Don’t confuse Lazy Loading in Entity Framework Core with
Lazy<T>
from .NET.
3 - Explicit Loading in Entity Framework Core
Finally, when we use explicit loading, it’s very similar to lazy loading, because we don’t load the data automatically, it has to be explicitly specified.
For example, if we load a user, to load the user’s workingExperiences
we do the following:
[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 to load and then retrieving its data with the Load()
/ LoadAsync()
method. Just like lazy loading, this results in a separate query.
One thing to note about Explicit Loading is that it can bypass lazy loading when it’s disabled (or if the proxy isn’t enabled), so it can be useful as a hack in certain scenarios.
Conclusion
As with everything in software development, the choice between Lazy Loading, Eager Loading, and Explicit Loading will depend on your particular situation and requirements. I hope this post helps you make an informed decision!
If there is any problem you can add a comment bellow or contact me in the website's contact form