使用 Cosmos DB 提供程序和 MediatR 的 Azure Functions 中的 DbContext 的线程问题

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

我在 Azure Functions 中将 Entity Framework Core 与 Cosmos DB 提供程序一起使用,当同时调用两个 HTTP 触发的函数时,我收到一个异常,指出

DbContext
是从另一个线程访问的。

这是我的设置:

  • DbContext
    使用
    AddDbContext()
    方法注册和配置。
  • 一个
    UnitOfWork
    类使用这个
    DbContext
    ,并且它被注册为
    scoped
    服务。
  • 几个
    MediatR
    RequestHandler
    类依赖于此
    UnitOfWork
    并使用
    RegisterServicesFromAssembly()
    方法进行注册。

程序.cs

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services =>
    {
        services.AddDbContext<MyDbContext>(options =>
        {
            options.UseCosmos(
                "https://your-cosmosdb-uri",
                "your-cosmosdb-key",
                "your-database-name"
            );
        }, ServiceLifetime.Transient);

        services.AddTransient<IUnitOfWork, UnitOfWork>();

        services.AddMediatR(cfg =>
            cfg.RegisterServicesFromAssembly(typeof(Program).Assembly)
        );
    })
    .Build();

host.Run();

MyFunctions.cs

public class MyFunctions
{
    private readonly IMediator _mediator;

    public MyFunctions(IMediator mediator)
    {
        _mediator = mediator;
    }

    [FunctionName("MyFunctionOne")]
    public async Task<IActionResult> RunOne(
        [HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req,
        CancellationToken cancellationToken)
    {
        var result = await _mediator.Send(new MyRequest(), cancellationToken);
        return new OkObjectResult(result);
    }

    [FunctionName("MyFunctionTwo")]
    public async Task<IActionResult> RunTwo(
        [HttpTrigger(AuthorizationLevel.Function, "get"] HttpRequest req,
        CancellationToken cancellationToken)
    {
        var result = await _mediator.Send(new MyRequest(), cancellationToken);
        return new OkObjectResult(result);
    }
}

UnitOfWork.cs

public class UnitOfWork : IUnitOfWork
{
    private readonly MyDbContext _context;
    private readonly MyRepository _repo;
    
    public UnitOfWork(MyDbContext context)
    {
        _context = context;
        _repo = new MyRepository(_context);
    }

    public MyRepository ProductRepository { get => _repo; }
}

MyRequestHandler.cs

public class MyRequestHandler : IRequestHandler<MyRequest, MyResponse>
{
    private readonly IUnitOfWork _unitOfWork;

    public MyRequestHandler(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    public async Task<MyResponse> Handle(MyRequest request, CancellationToken cancellationToken)
    {
        // Perform operations using UnitOfWork or any other logic
        await _unitOfWork.SaveChangesAsync(cancellationToken);

        // Create and return the response
        return new MyResponse
        {
            Result = $"Processed: {request.Data}"
        };
    }
}

对这个线程问题的原因有什么见解吗?

我已经在

Scoped
调用中明确尝试了
Transient
AddDbContext()
生命周期,但问题仍然存在。

multithreading dependency-injection entity-framework-core azure-functions azure-cosmosdb
1个回答
0
投票

问题是由使用

ConfigureFunctionsWorkerDefaults()
内部调用的单个扩展方法注册并添加到管道的中间件引起的,它没有使用
ConfigureServices()
方法正确注册。

TLDR - 在

ConfigureServices()
调用中专门注册您的依赖项。

© www.soinside.com 2019 - 2024. All rights reserved.