【问题标题】:Dependency Injected DbContext is always null依赖注入的 DbContext 始终为空
【发布时间】:2019-04-30 05:39:05
【问题描述】:

我在多个 ASP.NET (Core) 应用程序中使用 DI,其中 DbContext 被注入到控制器构造函数中,并且在对控制器的第一次请求时,构造函数运行并注入依赖项。

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

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

我已经研究了几天,尝试了一些手动模式,但我遇到了并发问题,整个项目现在感觉就像一个 hack。

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()。这会导致并发问题并完全否定@​​987654328@。

如果我想用 DI 注入 MyDbContext,就像我已经做过数百次一样,创建类的实例以在 QueueProcessor 内运行进程意味着我必须将 MyDbContext 的实例传递给构造函数我。 VS 在设计时将其标记出来。

我曾经尝试过尽可能地搞砸这个:

services.AddTransient(x => new QueueProcessor(x.GetService<MyDbContext>(), Configuration.GetConnectionString("MessageBus")));

我正在寻找一种更清洁的实现方式:

  • 调用QueueProcessor 中的方法以从项目开始处理 Azure 消息总线消息。
  • 在处理消息之前,我应该有一个 MyDbContext 的实例化实例,我可以使用它在消息被处理时持久化它们。
  • 不必使用Controller 来正确设置 DI。

有没有办法实现这一点,还是我完全错过了这里的标记?

【问题讨论】:

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


    【解决方案1】:

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

    1. Startup.cs 机会ConfigureServices 返回IServiceProvider 而不是void
    2. 使用:var serviceProvider = services.BuildServiceProvider(); 构建 serviceProvider
    3. 获取MyDbContext的实例:var context = serviceProvider.GetRequiredService&lt;MyDbContext&gt;();
    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;
        }
    

    【讨论】:

      猜你喜欢
      • 2021-08-11
      • 2016-05-10
      • 2021-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-06
      • 2020-05-27
      • 1970-01-01
      相关资源
      最近更新 更多