c# - 依赖注入(inject)的 DbContext 始终为 null

标签 c# entity-framework azure dependency-injection async-await

我在多个 ASP.NET(Core)应用程序中使用了 DI,其中 DbContext 被注入(inject)到 Controller 构造函数中,并且在向 Controller 发出第一个请求时,运行构造函数并注入(inject)依赖项。

我现在正在处理一个连接到 Azure 消息总线的 Web API 项目,处理和保存来自总线的数据,并为数据提供 API 终结点。处理和保存来自 Azure 消息总线的消息的类是 QueueProcessor .

我需要保留项目启动时的数据,这意味着我需要项目运行时的 DbContext 实例,而不是通过 API 端点查询数据时的 DbContext 实例。因此, QueueProcessor 的构造函数永远不会隐式调用,如果我想手动执行此操作,我需要 MyDbContext 的预先存在的实例传递给它。

我已经研究这个问题几天了,尝试了一些手动模式,但我遇到了并发问题,整个项目目前感觉就像是黑客攻击。

The closest question I've come across is this, which despite specifying non-controllers, the accepted answer requires a controller for the dependency to be injected.

这就是我目前正在做的事情:

    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。

有没有办法实现这一目标,或者我完全错过了这里的目标?

最佳答案

一个可行的解决方案,不确定它是否是最佳模式:

  1. Startup.cs机会ConfigureServices返回IServiceProvider而不是void .
  2. 使用: var serviceProvider = services.BuildServiceProvider(); 构建 serviceProvider
  3. 获取 MyDbContext 实例:var context = serviceProvider.GetRequiredService<MyDbContext>();
  4. 创建 QueueProcessor 的实例并通过 context到构造函数和调用方法以开始处理消息。
  5. 来自 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/

相关文章:

c# - 我可以防止类被非抽象对象继承吗?

c# - 使用 binaryformatter/deserialize 加载数据时检测损坏的文件

azure - 如何在 Azure Function App 上运行 PnP 脚本

azure - 从 Azure DevOps Pipeline 加载 Az.Kusto 2.0.0 PowerShell 模块时出现问题

azure - 可执行 kubelogin 失败,退出代码为 1

c# - WPF 多重绑定(bind) : OneWayToSource binding from TextBox updated via another binding doesnt work?

c# - 将 UI RectTransform 移动到世界位置

c# - AutoMapper.Mapper.Map 偶尔返回具有空属性的对象

c# - 将 null 参数传递给 LINQ where 子句

c# - Entity Framework - 如何在多个应用程序之间共享一些表