Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我应该如何将DbContext实例注入IHostedService? 问题:_C#_Asp.net_.net_Asp.net Core_.net Core - Fatal编程技术网

C# 我应该如何将DbContext实例注入IHostedService? 问题:

C# 我应该如何将DbContext实例注入IHostedService? 问题:,c#,asp.net,.net,asp.net-core,.net-core,C#,Asp.net,.net,Asp.net Core,.net Core,如何(使用标准依赖项注入)将DbContext实例注入IHostedService 我试过什么 我目前让我的IHostedService类在构造函数中获取一个MainContext(派生自DbContext)实例 当我运行应用程序时,我得到: 无法使用singleton“Microsoft.Extensions.Hosting.IHostedService”中的作用域服务“Microsoft.EntityFrameworkCore.DbContextOptions” 因此,我试图通过指定以下内容

如何(使用标准依赖项注入)将
DbContext
实例注入
IHostedService

我试过什么 我目前让我的
IHostedService
类在构造函数中获取一个
MainContext
(派生自
DbContext
)实例

当我运行应用程序时,我得到:

无法使用singleton“Microsoft.Extensions.Hosting.IHostedService”中的作用域服务“Microsoft.EntityFrameworkCore.DbContextOptions”

因此,我试图通过指定以下内容使
DbContextOptions
暂时化:

services.AddDbContext<MainContext>(options => 
                options.UseSqlite("Data Source=development.db"), ServiceLifetime.Transient);
services.AddDbContext(选项=>
options.UseSqlite(“数据源=development.db”)、ServiceLifetime.Transient);
在我的
启动
课程中

但是错误保持不变,即使根据
DbContextOptions
,passed应该具有在
AddDbContext
调用中指定的相同生存期


我不能将数据库上下文设置为单例,否则对它的并发调用将产生并发异常(因为数据库上下文不能保证线程安全)。

在托管服务中使用服务的一个好方法是在需要时创建作用域。这允许将服务/db上下文等与设置它们的生存期配置一起使用。理论上,不创建作用域可能会导致创建单例DbContext和不正确的上下文重用(EF Core 2.0和DbContext池)

为此,注入一个
IServiceScopeFactory
,并在需要时使用它创建一个作用域。然后从该范围中解析所需的任何依赖项。这还允许您将自定义服务注册为作用域依赖项,前提是您希望将逻辑移出托管服务,并仅使用托管服务触发某些工作(例如,定期触发任务-这将定期创建作用域,在此作用域中创建任务服务,同时还将注入db上下文)

公共类MyHostedService:IHostedService
{
专用只读设备ViceScopeFactory scopeFactory;
公共MyHostedService(IServiceScopeFactory范围工厂)
{
this.scopeFactory=scopeFactory;
}
公共工作
{
使用(var scope=scopeFactory.CreateScope())
{
var dbContext=scope.ServiceProvider.GetRequiredService();
…
}
}
…
}

您可以在构造函数中添加创建范围,如下所示:

 public ServiceBusQueueListner(ILogger<ServiceBusQueueListner> logger, IServiceProvider serviceProvider, IConfiguration configuration)
        {
            _logger = logger;
            _reportProcessor = serviceProvider.CreateScope().ServiceProvider.GetRequiredService<IReportProcessor>();
            _configuration = configuration;
        }

也许可以注入一个上下文工厂?e、 谢谢。注入
IServiceScopeFactory
和直接注入
IServiceProvider
之间有什么区别?
IServiceProvider
只提供根服务提供商。虽然它还实现了创建作用域的接口,但您可以使用它。但是一般的规则是尽可能少地请求。如果我在
using
子句中生成一个新线程(该线程将超过
DoWork
的生存期),并使用我在其中获取的一些服务,这样可以吗?或者作用域是否定义了服务何时被释放?EF提供的默认
AddDbContext()
方法将其注册为仅作用域。例如,在作用域结束时,EF将进行清理。您不希望在web应用程序中使用单例数据库上下文,否则您的所有组件都会与其他组件的事务发生冲突。所有使用db上下文实例的服务(通过构造函数注入)也需要确定作用域。@Peter,这将为您提供相同的实例。但是,我建议您在这里使用作用域生存期(或者暂时的,如果不可能的话),因为EF Core/DbContext不是线程安全的,并且从多个后台服务或控制器使用它可能会导致问题
 public ServiceBusQueueListner(ILogger<ServiceBusQueueListner> logger, IServiceProvider serviceProvider, IConfiguration configuration)
        {
            _logger = logger;
            _reportProcessor = serviceProvider.CreateScope().ServiceProvider.GetRequiredService<IReportProcessor>();
            _configuration = configuration;
        }
using Microsoft.Extensions.DependencyInjection;