dotnet / dotnet/EntityFramework.Docs
Clarify scopes of added services and how they interact
- Dominant language
- Mermaid
- Stars
- 1.7k
- Forks
- 2k
- Avg merge
- 7d 23h
- Merged PRs (30d)
- 16
Description
## Ask a question
Following the docs:
https://docs.microsoft.com/en-us/ef/core/dbcontext-configuration/#using-a-dbcontext-factory-eg-for-blazor
I am trying to add a DbContextFactory for my DbContext so my program can work with blazor. I am running blazor components that access services.
These services have repositories. And these repositories have a base class which implements a lot of repeating behaviour.
### Include your code
I am registering in startup:
```C#
services.AddDbContextFactory(options => options.UseSqlServer(config.DBConfiguration.ConnectionString));
```
The config is added as a singleton **before**
```C#
services.AddSingleton(_config);
```
Now I am using this in my repositories, which are transient. The base class is very big so I'll try to summarize it:
I still have the option to initialize from a `DbContext` directly for backwards compatibility.
```C#
internal abstract class Repository : IDisposable
where TEntity : class, IEntity
{
private DbSet _dbSet;
protected Repository(IDbContextFactory factory)
{
Context = factory.CreateDbContext();
}
protected Repository(FocusContext context)
{
Context = context;
}
protected FocusContext Context { get; init; }
protected DbSet DbSet => _dbSet ??= Context.Set();
public void Dispose()
{
GC.SuppressFinalize(this);
Context?.Dispose();
}
// ... a lot of methods that interact with the database go here.
// example
public async Task GetAsync(TKey id) =>
await DbSet
.AsQueryable()
.FirstOrDefaultAsync(ActivePredicate.And(i => i.Id.Equals(id)))
?? throw new ObjectNotFoundException();
}
```
The Repository is implemented like this:
```C#
internal class FeedItemLikeRepository : Repository
{
public FeedItemLikeRepository(IDbContextFactory factory)
: base(factory)
{
}
// custom repository implementation here...
}
```
Now it is called from a transient service. And that service is injected in to blazor with `@inject IService _service`.
So my question is, with my structure. How can I achieve working with the DbContextFactory so that in blazor I do not get an error stating that my DbContext is accessed before another operation has finished.
I have a pretty big API that is depending on these repositories. (Not the services, different services for CMS / API). So I can't just go around and do a big refactor. But I might need to.
### Include stack traces
When starting I get this breakpoint in the `Program.cs` file.
```
Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.EntityFrameworkCore.IDbContextFactory`1[Focus.Common.DB.FocusContext] Lifetime: Singleton ImplementationType: Microsoft.EntityFrameworkCore.Internal.DbContextFactory`1[Focus.Common.DB.FocusContext]': Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Focus.Common.DB.FocusContext]' from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory`1[Focus.Common.DB.FocusContext]'.) (Error while validating the service descriptor 'ServiceType: Focus.Common.App.Feed.Repositories.FeedItemRepository Lifetime: Transient ImplementationType: Focus.Common.App.Feed.Repositories.FeedItemRepository': Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Focus.Common.DB.FocusContext]' from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory`1[Focus.Common.DB.FocusContext]'.) (Error while validating the service descriptor 'ServiceType: Focus.Common.App.Feed.Repositories.FeedItemContentRepository Lifetime: Transient ImplementationType: Focus.Common.App.Feed.Repositories.FeedItemContentRepository': Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Focus.Common.DB.FocusContext]' from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory`1[Focus.Common.DB.FocusContext]'.) (Error while validating the service descriptor 'ServiceType: Focus.Common.App.Feed.Repositories.FeedItemContentLabelRepository Lifetime: Transient ImplementationType: Focus.Common.App.Feed.Repositories.FeedItemContentLabelRepository': Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Focus.Common.DB.FocusContext]' from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory`1[Focus.Common.DB.FocusContext]'.) (Error while validating the service descriptor 'ServiceType: Focus.Common.App.Feed.Repositories.FeedItemLikeRepository Lifetime: Transient ImplementationType: Focus.Common.App.Feed.Repositories.FeedItemLikeRepository': Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Focus.Common.DB.FocusContext]' from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory`1[Focus.Common.DB.FocusContext]'.) (Error while validating the service descriptor 'ServiceType: Focus.Common.App.Feed.Services.IFeedService Lifetime: Transient ImplementationType: Focus.Common.App.Feed.Services.FeedService': Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Focus.Common.DB.FocusContext]' from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory`1[Focus.Common.DB.FocusContext]'.) (Error while validating the service descriptor 'ServiceType: Focus.Common.App.Feed.Services.IFeedManagementService Lifetime: Transient ImplementationType: Focus.Common.App.Feed.Services.FeedManagementService': Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Focus.Common.DB.FocusContext]' from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory`1[Focus.Common.DB.FocusContext]'.)
```
### Include provider and version information
EF Core version: 5.0.0
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: `net5.0`
Operating system: Windows 10
IDE: Visual Studio 16.9.2
Contributor guide
Assessment
This issue has not been assessed yet.