[英].NET Core 3.1 BackgroundService - Consume RabbitMQ and insert using EntityFrameCore
I'm currently writing a background service which reads messages from a queue and inserts these values into a mssql database.我目前正在编写一个后台服务,它从队列中读取消息并将这些值插入到 mssql 数据库中。 I'm using entityframecore to insert the values into the context.
我正在使用 entityframecore 将值插入到上下文中。
Now I'm having an issue with the context.现在我遇到了上下文问题。 I keep getting the error:
我不断收到错误:
InvalidOperationException: A second operation started on this context before a previous operation completed. InvalidOperationException:在前一个操作完成之前在此上下文上启动了第二个操作。 Any instance members are not guaranteed to be thread safe.
不保证任何实例成员都是线程安全的。 Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()
Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()
Now I know this is an issue with async, but still...现在我知道这是异步的问题,但仍然......
I fixed this by defining a new scope at the beginning.我通过在开始时定义一个新的 scope 来解决这个问题。 But I'm not sure if this is the way to go... Here is my code currently:
但我不确定这是否是通往 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);
}
};
You can see that I just pass the context to the other methods and.Add() entities.您可以看到我只是将上下文传递给其他方法和 .Add() 实体。 Is this the way to go?
这是通往 go 的路吗?
Thanks for the help!谢谢您的帮助!
Kind regards亲切的问候
The Entity Framework does not support concurrent operation on a single DbContext
.实体框架不支持对单个
DbContext
进行并发操作。 If you want to use multiple threads to communicate with your database then you have to create multiple DbContext instance.如果要使用多个线程与数据库通信,则必须创建多个 DbContext 实例。 See MSDN
见 MSDN
So, in short the DbContext is not thread-safe, that's why the suggested way to register your DbContext in your DI container is to use Transient lifecycle:因此,简而言之,DbContext 不是线程安全的,这就是为什么在 DI 容器中注册 DbContext 的建议方法是使用Transient生命周期:
services.AddDbContext<YourDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString(Constants.YourConnectionString)),
ServiceLifetime.Transient);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.