使用Mediatr触发Azure功能队列-DbContext错误

时间:2019-03-31 12:44:15

标签: entity-framework-core azure-functions dbcontext azure-functions-runtime mediatr

我正在实现Queue触发的Azure函数-我正在使用称为Mediatr的Mediator Pattern库来增强命令查询隔离-并根据以下说明在Azure Function中使用最新的运行时(2.0.12382.0)构造函数依赖项注入教程 https://devkimchi.com/2019/02/22/performing-constructor-injections-on-azure-functions-v2/

对于每个Azure函数触发器,我都调用Mediatr CommandHandler,但收到错误消息:

  

“第二个操作在此操作之前开始于此上下文。这通常是由使用相同DbContext实例的不同线程引起的,但是不能保证实例成员是线程安全的。这也可能是由嵌套引起的正在客户端上评估查询,如果是这种情况,请重写查询以避免嵌套调用。”

该错误表明我正在尝试从并行任务访问DbContext的同一实例。但是我只有一个命令处理程序(Mediatr Handler)和一个查询处理程序。我为此使用构造函数注入

我试图在启动时将Meditr服务更改为临时服务,但在测试Azure功能仿真器中的功能时仍然收到相同的错误

启动类

public class StartUp : IWebJobsStartup
{

    public void Configure(IWebJobsBuilder builder)
    {
        var configuration = new ConfigurationBuilder()
             .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
             .AddEnvironmentVariables()
             .Build();
        var connection = configuration.GetConnectionString("Default"); 
        builder.Services.AddDbContext<CoreDBContext>(options =>
        {
            options.UseSqlServer(connection, p =>
            {
                p.MigrationsAssembly("B12Core.Persistence");
            });
        }
        );
        builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>));
        builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPerformanceBehaviour<,>));
        builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestValidationBehavior<,>));
        builder.Services.AddMediatR(p =>
        {
            p.AsTransient();

        }, typeof(CreateMessageCommand).GetTypeInfo().Assembly);
    }
}

完全错误

  

System.Private.CoreLib:执行函数Function1时发生异常。 Microsoft.EntityFrameworkCore:在上一个操作完成之前,在此上下文上启动了第二个操作。这通常是由使用同一DbContext实例的不同线程导致的,但是不能保证实例成员是线程安全的。如果是这种情况,也可能是因为在客户端上评估了嵌套查询,如果是这种情况,请重写查询以避免嵌套调用。

1 个答案:

答案 0 :(得分:0)

通过将数据库上下文注入生存期更改为ServiceLifetime.Transient解决了该问题

 builder.Services.AddDbContext<CoreDBContext>(options =>
            {
                options.UseSqlServer(connection, p =>
                {
                   p.MigrationsAssembly("Presistence");
                });
            },ServiceLifetime.Transient
            );