我在多个 ASP.NET(Core)应用程序中使用了 DI,其中 DbContext 被注入(inject)到 Controller 构造函数中,并且在向 Controller 发出第一个请求时,运行构造函数并注入(inject)依赖项。
我现在正在处理一个连接到 Azure 消息总线的 Web API 项目,处理和保存来自总线的数据,并为数据提供 API 终结点。处理和保存来自 Azure 消息总线的消息的类是 QueueProcessor
.
我需要保留项目启动时的数据,这意味着我需要项目运行时的 DbContext 实例,而不是通过 API 端点查询数据时的 DbContext 实例。因此, QueueProcessor
的构造函数永远不会隐式调用,如果我想手动执行此操作,我需要 MyDbContext
的预先存在的实例传递给它。
我已经研究这个问题几天了,尝试了一些手动模式,但我遇到了并发问题,整个项目目前感觉就像是黑客攻击。
这就是我目前正在做的事情:
public void ConfigureServices(IServiceCollection services)
{
services.AddHangfire(x => x.UseSqlServerStorage(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContextPool<MyDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("default")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
然后我必须创建我的 QueueProcessor
的新实例并使用var context = new MyDbContext()
在构造函数内部。这会导致并发问题并完全否定 DI
.
如果我想注入(inject)MyDbContext
像我已经做过数百次一样,使用 DI 创建类的实例来运行 QueueProcessor
内的进程意味着我必须传递 MyDbContext
的实例给我自己的构造函数。 VS 在设计时标记了这一点。
我曾经尝试通过以下方式尽可能地搞砸这个:
services.AddTransient(x => new QueueProcessor(x.GetService<MyDbContext>(), Configuration.GetConnectionString("MessageBus")));
我正在寻找一种更干净的方式来实现:
- 调用
QueueProcessor
中的方法从项目启动时处理 Azure 消息总线消息。 - 在处理消息之前,我应该有一个
MyDbContext
的实例化实例当消息被处理时我可以用它来保存消息。 - 不必使用
Controller
正确设置 DI。
有没有办法实现这一目标,或者我完全错过了这里的目标?
最佳答案
一个可行的解决方案,不确定它是否是最佳模式:
- 在
Startup.cs
机会ConfigureServices
返回IServiceProvider
而不是void
. - 使用:
var serviceProvider = services.BuildServiceProvider();
构建 serviceProvider - 获取 MyDbContext 实例:
var context = serviceProvider.GetRequiredService<MyDbContext>();
- 创建
QueueProcessor
的实例并通过context
到构造函数和调用方法以开始处理消息。 - 来自
ConfigureServices
,返回新的serviceProvider
.
完整代码块:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("...")));
var serviceProvider = services.BuildServiceProvider();
var localMyDbContext = serviceProvider.GetRequiredService<MyDbContext>();
Processor = new QueueProcessor(localDbContext, Configuration.GetConnectionString("Other"));
Processor.RunAsync().GetAwaiter().GetResult();
return serviceProvider;
}
关于c# - 依赖注入(inject)的 DbContext 始终为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53517321/