c# - 在 RabbitMQ Consumer(单例服务)中使用 DbContext

标签 c# .net asp.net-core rabbitmq

我有一个工作正常的 RabbitMQ 单例,但每当消息到达时都依赖于作用域服务:

consumer.Received += _resourcesHandler.ProcessResourceObject; //Scoped Service

我的服务是这样注册的:

services.AddScoped<IHandler, Handler>();
services.AddSingleton<RabbitMqListener>();

作用域服务构造函数使用 DI 作为 Db 上下文:

private readonly ApplicationDbContext _appDbContext;

public ResourcesHandler(ApplicationDbContext appDbContext)
{
    _appDbContext = appDbContext;
}

此作用域服务调用 Db 上下文,以便在收到消息时将属性插入数据库。

但是,由于作用域服务的生命周期不同,因此启动失败。

有更好的方法吗?我可以将作用域服务设为单例,但随后我会遇到使用 DbContext 作为依赖项的问题。

DI 中用于在单例服务中调用 dbContext 的“协议(protocol)”是什么?

我可以使用 using 语句来确保它已被处置,但是我必须改为使用 DI 来传递 DbContextOptions。这是实现这一目标的唯一方法吗?

最佳答案

一种方法是自己创建作用域。通常 asp.net core 在请求开始时为您创建范围,并在请求结束时关闭范围。但在你的情况下 - rabbitmq 消息消费与 http 请求根本无关。不过,您可以说,每个消息处理都代表其自己的范围。

在这种情况下,注入(inject) IServiceProviderRabbitMqListener (在下面表示为 _provider 私有(private)字段)然后:

private void OnMessageReceived(Message message) {
    using (var scope = _provider.CreateScope()) {
        var handler = scope.ServiceProvider.GetRequiredService<IHandler>();
        handler.ProcessResourceObject(message);
    }
}

另一种方法是注册 ApplicationDbContext容器中的工厂(除了常规范围内的注册)。工厂将返回 ApplicationDbContext 的新实例这将是调用者的责任来处理它。例如:

services.AddSingleton<Func<ApplicationDbContext>>(() =>
{
    var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
    optionsBuilder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
    return new ApplicationDbContext(optionsBuilder.Options);
});

然后就可以注册了IHandler作为单例(并且不像现在那样限定范围)并注入(inject) Func<ApplicationDbContext>在其构造函数中:

private readonly Func<ApplicationDbContext> _appDbContextFactory;

public ResourcesHandler(Func<ApplicationDbContext> appDbContextFactory)
{
    _appDbContextFactory = appDbContextFactory;
}

然后,每当您需要在处理程序中处理消息时——您自己管理上下文:

using (var context = _appDbContextFactory()) {
    // do stuff
}

关于c# - 在 RabbitMQ Consumer(单例服务)中使用 DbContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49728884/

相关文章:

c# - 运行 SP 超过 30 秒时超时

javascript - Web浏览器注入(inject)Javascript将焦点设置到第一个输入框

c# - 使用 model.Filters.Add<TFilterType>() 配置 ASP.NET Core razor 页面过滤器

c# - 使用剪切或复制从剪贴板粘贴文件

.net - YAML 中的单个感叹号有什么作用?

javascript - Dropzone JS 不是部分 View 中的函数错误

asp.net-core - 带有 Angular 5 的 ASP.NET Core -- 何时使用 Assets 文件夹与 wwwroot 文件夹?

c# - Visual Studio 2008 中重构菜单的快捷键(重命名、 "using"等)?

c# - 生成带有校验位的唯一公共(public)用户标识符

c# - 未显示 ASP.Net 菜单栏