I have implemented custom ASP.NET Core middleware which uses database context as a dependency. Sometimes it throws the following exception for the very first request coming to the API:
An unhandled exception has occurred while executing the request. System.InvalidOperationException: An attempt was made to use the context while it is being configured. A DbContext instance cannot be used inside OnConfiguring since it is still being configured at this point. This can happen if a second operation is started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.`
I could reproduce it only when API was called from SPA. When I called API from Swagger everything was working just fine. Changing order of middlewares didn't help. After digging around I realized that middleware was instantiated once per application while the database context had a scoped lifetime. So perhaps the issue was in injecting my database context right into middleware's constructor. I fixed my code by removing injection of database context from constructor and injecting it directly to
InvokeAsync method. This helped and exception gone.
Though I solved my issue I don't quite understand yet how it worked at all. As far as I understand the EF.Core database context by default is registered with scoped lifetime what in terms of ASP.NET Core application means that new context gets instantiated for every new request and disposed upon its completion. Because I injected the database context into middleware's constructor it should have been disposed right after first request finished and this exceptions or another one saying that it's trying to use already-disposed context should have been thrown. Also it's absolutely not clear to me why this error was happening only when API got called from SPA while it was working good for all Swagger requests.
Seems I have figured it out. I didn't mention that I use Autofac service provider instead of default service provider in my application which in fact was worth to mention. According to ASP.NET Core documentation
The Default Service Provider in Development environment performs checks to verify that:
- Scoped services aren't directly or indirectly resolved from the root service provider.
- Scoped services aren't directly or indirectly injected into singletons.
Apparently Autofac service provider doesn't perform such checks so it allows to inject scoped services from root service provider. And according to documentation
The root service provider's lifetime corresponds to the app/server's lifetime when the provider starts with the app and is disposed when the app shuts down.
This is why my application worked as expected though I injected scoped service into singleton. It used the instance of
DbContext resolved from the root service provider and sometime I could get such situation when I tried to perform query to database before the context was actually initialized. This explains the sporadic nature of this issue.