在 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.
所以,我使用 IServiceScopeFactory 创建了一个作用域,它成功了
var scopeFactory = app.ApplicationServices.GetService<IServiceScopeFactory>();
using var scope = scopeFactory.CreateScope();
var myService = scope.ServiceProvider.GetService<IMyService>();
通过接口 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 scopedIMyDbContext
, 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.
所以,我使用 IServiceScopeFactory 创建了一个作用域,它成功了
var scopeFactory = app.ApplicationServices.GetService<IServiceScopeFactory>();
using var scope = scopeFactory.CreateScope();
var myService = scope.ServiceProvider.GetService<IMyService>();