在 EFCore 3 中通过接口解析 DbContext

Resolve DbContext by Interface in EFCore 3

通过接口 register/resolve DbContext 的正确方法是什么?


上下文:

我有多个 Web 服务,每个服务都有不同的 dbcontext。

因为我需要在共享项目中编写一些通用功能,所以我编写了一个由每个 dbcontext 实现的接口,因此我可以拥有一组共享功能 "dbcontext-implementation-agnostic" 只需注入 dbcontext 接口。

在每个项目中,每个 dbcontext 已被其实现使用和注入,但我只想在公共功能项目中使用它的接口。

所以,在每个网络服务中我都会有类似的东西:

services.AddDbContext<IMyDbcontext, MyDbcontext>(options =>
{
    options.UseSqlServer(configuration.GetConnectionString("MyDbContext"));
});
services.AddTransient<ISharedService, SharedService>();

并在共享项目中

public class SharedService : ISharedService
{
    public SharedService(IMydbcontext context)
    {
        [...]
    }

    [...]
}

IMyDbcontext就像

public interface IMyDbcontext
{
    DbSet<SharedSettings> Settings { get; set; }

    int SaveChanges(bool acceptAllChangesOnSuccess);
    int SaveChanges();
    Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default);
    Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
}

我需要 Startup.cs 内的 ISharedService - Configure() with

app.ApplicationServices.GetService<ISharedService>();

我一直在谷歌上搜索并尝试了不同的方法,但我找不到有效的方法...

我试过使用转发器,如下所示:(按照建议

services.AddDbContext<MyDbContext>();
services.AddScoped<IMyDbContext>(provider => provider.GetRequiredService<MyDbContext>());

但是,虽然我在解决具体 MyDbContext 时没有问题,但每当我尝试解决 IMyDbContext

时都会收到此错误

System.InvalidOperationException: 'Cannot resolve 'Blah.IMyService' from root provider because it requires scoped service 'Blah.IMydbcontext'.'

其中 IMyService 被注册为瞬态,它的实现构造函数是

public MyService(IMydbcontext context)

我也试过这样注册dbcontext

services.AddDbContext<IMyDbContext, MyDbContext>();

但是,当我尝试解析 MyDbContext 时,我得到 null,我不明白为什么

正如/u/AngularBeginner指出的:

The IMyService requires a scoped IMyDbContext, but within your startups Configure() method you don't have a scope.

You can make your IDbContext transient (if that's acceptable to you).

Alternatively you can try to create a temporary scope using the CreateScope() method, then get your IMyService from that new scoped provider.

Source

所以,我使用 IServiceScopeFactory 创建了一个作用域,它成功了

var scopeFactory = app.ApplicationServices.GetService<IServiceScopeFactory>();   
using var scope = scopeFactory.CreateScope();
var myService = scope.ServiceProvider.GetService<IMyService>();