graphql-dotnet: Using scoped DbContext in DataLoaders - System.InvalidOperationException: A second operation started on this context before a previous operation completed
Summary
When using a scoped DbContext with multiple DataLoaders all resolving at the same time, I get the following error:
GraphQL.ExecutionError: Error trying to resolve agent. ---> System.InvalidOperationException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.\n at Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()\n...
I can’t find any documentation or issues directly related to this, which leads me to believe that I’m using it wrong.
One obvious solution is to change my service registration for the DbContext to Transient, instead of scoped (default), but this will require a large refactor and I have seen a few references that all strongly discourage this.
Any ideas?
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 22 (4 by maintainers)
Commits related to this issue
- Change lifetime for DbContext from Scoped to Transient Nested GraphQL queries are executed in parallel. As result, if the same instance of DbContext is shared between these queries, the following err... — committed to CodeFuller/music-library-api by CodeFuller 5 years ago
- Inject Func<JellypicContext> to prevent DbContext thread problem https://github.com/graphql-dotnet/graphql-dotnet/issues/863#issuecomment-578616371 — committed to johnnyoshika/jellypic by johnnyoshika 4 years ago
- Inject Func<JellypicContext> to prevent DbContext thread problem https://github.com/graphql-dotnet/graphql-dotnet/issues/863#issuecomment-578616371 — committed to johnnyoshika/jellypic by johnnyoshika 4 years ago
- Inject Func<JellypicContext> to prevent DbContext thread problem https://github.com/graphql-dotnet/graphql-dotnet/issues/863#issuecomment-578616371 — committed to johnnyoshika/jellypic by johnnyoshika 4 years ago
- Inject Func<JellypicContext> to prevent DbContext thread problem https://github.com/graphql-dotnet/graphql-dotnet/issues/863#issuecomment-578616371 — committed to johnnyoshika/jellypic by johnnyoshika 4 years ago
- Inject Func<JellypicContext> to prevent DbContext thread problem https://github.com/graphql-dotnet/graphql-dotnet/issues/863#issuecomment-578616371 — committed to johnnyoshika/jellypic by johnnyoshika 4 years ago
- Inject Func<JellypicContext> to prevent DbContext thread problem https://github.com/graphql-dotnet/graphql-dotnet/issues/863#issuecomment-578616371 — committed to johnnyoshika/jellypic by johnnyoshika 4 years ago
- Inject Func<JellypicContext> to prevent DbContext thread problem https://github.com/graphql-dotnet/graphql-dotnet/issues/863#issuecomment-578616371 — committed to johnnyoshika/jellypic by johnnyoshika 4 years ago
- Inject Func<JellypicContext> to prevent DbContext thread problem https://github.com/graphql-dotnet/graphql-dotnet/issues/863#issuecomment-578616371 — committed to johnnyoshika/jellypic by johnnyoshika 4 years ago
you can work around this by implementing your own execution strategy
https://github.com/graphql-dotnet/graphql-dotnet/pull/1026
Unfortunately, DbContext is not capable of doing multiple requests at the same time. Using transient DbContext is an option, but you have to carefully dispose of them later, and usage of DbContextFactory may be broken. You may also try creating a custom context in your resolve methods (or somewhere in you dataloader methods) and use it to work with DbContext.
I solved this by injecting
Func<DbContext>instead ofDbContextand instantiate a new DbContext every time I need one. This way DbContext is never shared across multiple threads.Register
Func<DbContext>in Startup.cs afterMyDbContextis registered:Use
Func<DbContext>in Queries. Example:I’m not sure if I configured this properly, so I’d love to get some feedback on this.
Hello, I have the same issue. Can someone give a complete example of the execution strategy class along with their startup.cs file please.
Thanks