如何从IHostingService实例化DbContext



我有一个类,派生自BackgroundService(IHostedService)运行后台任务。这将添加到我的服务使用builder.Services.AddHostedService<BackgroundTaskService>()

BackgroundService的任务在web应用程序的整个持续时间内运行,检查是否有排队的数据要处理。

我的问题是,我如何从这段代码实例化DbContext的实例?

我可以让BackgroundTaskService构造函数接受DbContext。但这难道不会让DbContext永远开放吗?

如果不复制所有的代码来扫描我的设置文件的连接字符串等,我怎么能实例化它?

推荐的方法是注入IDbContextFactory<TContext>,如下文中所述:使用DbContext工厂(例如Blazor)

一些应用程序类型(例如ASP。. NET Core Blazor)使用依赖注入,但不创建与DbContext生存期一致的服务范围。即使存在这样的对齐,应用程序也可能需要在此范围内执行多个工作单元。例如,在单个HTTP请求中包含多个工作单元。

在这些情况下,AddDbContextFactory可以用来注册一个工厂来创建DbContext实例。

public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextFactory<ApplicationDbContext>(
options =>
options.UseSqlServer(@"Server=(localdb)mssqllocaldb;Database=Test"));
}

然后在控制器中:

private readonly IDbContextFactory<ApplicationDbContext> _contextFactory;
public MyController(IDbContextFactory<ApplicationDbContext> contextFactory)
{
_contextFactory = contextFactory;
}
public void DoSomething()
{
using (var context = _contextFactory.CreateDbContext())
{
// ...
}
}

你可以使用作用域服务工厂。参考

这里有一个例子:

// Injection
public class DataApi : BackgroundService
{
private readonly ILogger<DataApi> logger;
private readonly IServiceScopeFactory scopeFactory;
public DataApi(ILogger<DataApi> _logger, IConfiguration _cfg, IServiceScopeFactory _sSF)
{
logger = _logger;
scopeFactory = _sSF;
// e.g. data from appsettings.json 
// var recovery = _cfg["Api:Recovery"];
}
// ...
// Usage
protected async Task DataCollector()
{
logger.LogInformation("Collector");
using (var scope = scopeFactory.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<MyDbContext>();
var myList = await db.MyEntity
.AsNoTracking()
.Where(t => t.active)
.ToListAsync();
if (myList.Count == 0)
{
logger.LogInformation("Empty...");
return;
}
// logic...
}
await Task.CompletedTask;
}

最新更新