Reputation: 1958
Hello,
I have an ASP.NET Core app with EF Core running on postgresql db server. I ran into this problem:
When I access DB from a controller, everything works fine. But when I try to access DB from a middleware, an exception occurs (both under higher request load):
System.InvalidOperationException: An operation is already in progress.
at Npgsql.NpgsqlConnector.StartUserAction(ConnectorState newState)
at Npgsql.NpgsqlCommand.<ExecuteDbDataReaderInternalAsync>d__4.MoveNext()
...
Sample code:
DB configuration
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; }
...
}
The middleware
public async Task Invoke(HttpContext context)
{
var test = await _context.SomeItems.FirstOrDefaultAsync();
}
An controller
public async Task<SomeItem> GetStuff()
{
return await _context.SomeItems.FirstOrDefaultAsync();
}
My question is - Why is the controller able to serve many async concurrent request and the middleware not? And how can I get it work too? I'm little bit lost in asynchronicity and ASP.NET anatomy right now.
Thank you in advance.
Upvotes: 0
Views: 838
Reputation: 24123
When you use constructor injection in middleware, if dependency lifetime is scoped it causes captive dependency. You used ApplicationDbContext
and it is scoped. So the problem probably occurs from this reason. To avoid, you can pass dependency into Invoke
method as a parameter:
public async Task Invoke(HttpContext context, ApplicationDbContext _context)
{
var test = await _context.SomeItems.FirstOrDefaultAsync();
}
Upvotes: 1
Reputation: 6749
I'm not sure why you're getting the error but both methods aren't the same. middleware doesn't have a return type and controller does 'SomeItem'. Also, just return the Async method right away and drop the asnyc await from the Task.
public async Task GetStuff()
{ return await _context.SomeItems.FirstOrDefaultAsync(); }
public Task<SomeItem> GetStuff()
{
return _context.SomeItems.FirstOrDefaultAsync();
}
Upvotes: 0