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

问题描述 投票:0回答:1

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

现在我在上下文方面遇到了一个问题。我一直得到错误信息。

InvalidOperationException: 在前一个操作完成之前,对这个上下文的第二个操作已经开始。任何实例成员都不能保证线程安全.Microsoft.EntityFrameworkCore.Internal.ConurrencyDetector.EnterCriticalSection()

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

我通过在开头定义一个新的作用域来解决这个问题。但我不确定这是否是正确的方法......这是我目前的代码。

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()实体. 这样做对吗?

谢谢你的帮助

谢谢你的帮助

c# rabbitmq entity-framework-core
1个回答
0
投票

实体框架不支持在单个实体上的并发操作。DbContext. 如果你想使用多个线程与数据库通信,那么你必须创建多个DbContext实例。参见MSDN 所以,简而言之,DbContext不是线程安全的,这就是为什么建议在DI容器中注册你的DbContext的方法是使用 瞬息万变 生命周期。

services.AddDbContext<YourDbContext>(options =>  
  options.UseSqlServer(Configuration.GetConnectionString(Constants.YourConnectionString)),
  ServiceLifetime.Transient);
© www.soinside.com 2019 - 2024. All rights reserved.