dotnet / dotnet/EntityFramework.Docs

Clarify scopes of added services and how they interact

Open
#3,259 8 comments 0 reactions 0 assignees View on GitHub
area-context-management
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.