.NET 8 Blazor - DbContextFactory and EF Core Lazy Loading
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
### Is there an existing issue for this?
- [X] I have searched the existing issues
### Describe the bug
The latest guidance from Microsoft for using EF Core with Blazor is to use DbContextFactory and short-lived DbContent instances (confirmed here https://learn.microsoft.com/en-us/aspnet/core/blazor/blazor-ef-core?view=aspnetcore-8.0#new-dbcontext-instances).
The basic pattern is to use CreateDbContext() in your data access methods. The following is an example of method which returns a collection of users:
```
public IEnumerable GetUsers()
{
using var db = _dbContextFactory.CreateDbContext();
return db.User;
}
```
Note that when using this pattern it is not possible to use the standard EF Core lazy loading behavior. This is because the DbContext is disposed as soon as the data access is complete. If you try to defer performing any additional operations on the DbSet it will throw an exception. For example if we add an .OrderBy():
```
public IEnumerable GetUsers()
{
using var db = _dbContextFactory.CreateDbContext();
return ctx.User.OrderBy(item => item.Name);
}
```
It will result in the following exception:
"Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances."
The solution to this problem is to add .ToList() to instruct EF Core to perform eager loading on the collection:
```
public IEnumerable GetUsers()
{
using var db = _dbContextFactory.CreateDbContext();
return ctx.User.OrderBy(item => item.Name).ToList();
}
```
However this means that your Blazor application will not be able to utilize lazy loading, which is one of the most significant performance features offered by EF Core.
Since DbContextFactory is the recommended guidance, I was curious how aspnetcore handled this challenge in its own classes which interact with EF Core. A few examples:
1. The new CRUD templates for Blazor which were introduced recently for scaffolding code. It appears they do not follow the guidance - they continue to use DbContext (which has been well documented to to not align with Blazor's process model). In fact someone already logged an issue about this: https://github.com/dotnet/aspnetcore/issues/54539
2. The .NET Identity classes in .NET 8. It appears they do not use DbContextFactory either. Someone has logged an issue here: https://github.com/dotnet/aspnetcore/issues/42260
So since there are no examples on the recommended approach for using DbContextFactory, I would request that the documentation be updated with some examples. Specifically, it would be helpful if this challenge related to lazy loading is addressed in the docs so that it is clear on whether Microsoft is recommending that developers utilize an eager loading approach with EF Core when it comes to Blazor.
### Expected Behavior
Improved documentation and actual DbContextFactory usage in aspnetcore implementations.
### Steps To Reproduce
_No response_
### Exceptions (if any)
_No response_
### .NET Version
8.0
### Anything else?
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.