从中间件访问数据库时出现操作已经在进行中的错误
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();
}
你好,
我在 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();
}