繁体   English   中英

.NET Core 3.1 BackgroundService - 使用 RabbitMQ 并使用 EntityFrameCore 插入

[英].NET Core 3.1 BackgroundService - Consume RabbitMQ and insert using EntityFrameCore

我目前正在编写一个后台服务,它从队列中读取消息并将这些值插入到 mssql 数据库中。 我正在使用 entityframecore 将值插入到上下文中。

现在我遇到了上下文问题。 我不断收到错误:

InvalidOperationException:在前一个操作完成之前在此上下文上启动了第二个操作。 不保证任何实例成员都是线程安全的。 Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()

现在我知道这是异步的问题,但仍然......

我通过在开始时定义一个新的 scope 来解决这个问题。 但我不确定这是否是通往 go 的方式......这是我目前的代码:

consumer.Received += async (ch, ea) =>
            {
                using (var scope = _scope.BeginLifetimeScope())
                {
                    var context = scope.Resolve<DatabaseContext>();
                    var content = Encoding.UTF8.GetString(ea.Body.ToArray());

                    var message = JsonConvert.DeserializeObject<RabbitMQMessageType>(content);

                    switch (message.Type)
                    {
                        case "config":
                            await HandleConfigMessage(message.Body, context);
                            break;
                        case "measurement":
                            await HandleMeasurementMessage(message.Body, context);
                            break;
                        case "log":
                            await HandleLogMessage(message.Body);
                            break;
                    }

                    _channel.BasicAck(ea.DeliveryTag, false);
                }
            };

您可以看到我只是将上下文传递给其他方法和 .Add() 实体。 这是通往 go 的路吗?

谢谢您的帮助!

亲切的问候

实体框架不支持对单个DbContext进行并发操作。 如果要使用多个线程与数据库通信,则必须创建多个 DbContext 实例。 见 MSDN
因此,简而言之,DbContext 不是线程安全的,这就是为什么在 DI 容器中注册 DbContext 的建议方法是使用Transient生命周期:

services.AddDbContext<YourDbContext>(options =>  
  options.UseSqlServer(Configuration.GetConnectionString(Constants.YourConnectionString)),
  ServiceLifetime.Transient);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM