从中间件访问数据库时出现操作已经在进行中的错误

An operation is already in progress error while accessing DB from middleware

你好,

我在 postgresql 数据库服务器上有一个带有 EF Core 运行 的 ASP.NET Core 应用程序。我运行陷入这个问题:

当我从控制器访问数据库时,一切正常。 但是当我尝试从中间件访问数据库时,出现异常(均在更高的请求负载下):

System.InvalidOperationException: An operation is already in progress.
   at Npgsql.NpgsqlConnector.StartUserAction(ConnectorState newState)
   at Npgsql.NpgsqlCommand.<ExecuteDbDataReaderInternalAsync>d__4.MoveNext()
...

示例代码:


数据库配置

private void ConfigureDatabase(IServiceCollection services)
{
    var connectionString = ConfigObject.Value.DbContextSettings.ConnectionString;
    services.AddDbContext<ApplicationDbContext>(opts => opts.UseNpgsql(connectionString));
}

DbContext

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, Role, Guid>
  {

        ...

        public DbSet<SomeItem> SomeItems { get; set; }

        ...
  }

中间件

public async Task Invoke(HttpContext context)  
        {
                var test = await _context.SomeItems.FirstOrDefaultAsync();
        }

一个控制器

public async Task<SomeItem> GetStuff()  
        {
                return await _context.SomeItems.FirstOrDefaultAsync();
        }

我的问题是 - 为什么控制器能够处理许多异步并发请求而中间件不能?我怎样才能让它工作呢?我现在有点迷失在异步性和 ASP.NET 解剖中。

提前致谢。

我不确定您为什么会收到错误消息,但这两种方法并不相同。中间件没有 return 类型,而控制器有 'SomeItem'。此外,只需立即 return Async 方法并从任务中删除 asnyc await。

public async Task GetStuff()
{ return await _context.SomeItems.FirstOrDefaultAsync(); }

public Task<SomeItem> GetStuff()  
{
    return _context.SomeItems.FirstOrDefaultAsync();
}

当您在中间件中使用构造函数注入时,如果依赖生命周期被限定,则会导致 captive dependency。您使用了 ApplicationDbContext 并且它是有范围的。所以问题很可能是由于这个原因引起的。为避免这种情况,您可以将依赖项作为参数传递给 Invoke 方法:

    public async Task Invoke(HttpContext context, ApplicationDbContext _context)  
    {
         var test = await _context.SomeItems.FirstOrDefaultAsync();
    }