There are long-lived objects on the site, which at intervals of 4-5 minutes do something and write the results into the database. For myself, I decided that to keep the connection to the database open all the time, and Func<ApplicationDbContext> unnecessarily and pre-registered all this in the configuration.
services.AddEntityFrameworkMySql().AddDbContextPool<ApplicationDbContext>(options => { options.UseMySql(Configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly("VFL.Web").EnableRetryOnFailure()); } services.AddTransient<Func<ApplicationDbContext>>(s => s.GetRequiredService<ApplicationDbContext>); And all this works with periodic success sometimes giving an exception of the following form:
2019-03-28 13:03:43.2027||ERROR|VFL.Web.Filters.PermissionHandler|Permission check failed System.InvalidOperationException: A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext, however instance members are not guaranteed to be thread safe. This could also be caused by a nested query being evaluated on the client, if this is the case rewrite the query avoiding nested invocations. at Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection() at Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSectionAsync(CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteSingletonAsyncQuery[TResult](QueryContext queryContext, Func`2 compiledQuery, IDiagnosticsLogger`1 logger, Type contextType) at VFL.Web.Filters.PermissionHandler.HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) in /root/betprofit-server/VFL.Web/Filters/Permissions.cs:line 62 And sometimes it changes to
Cannot access a disposed object. This is a process that has been resolved from This may occur if you are calling Dispose () If you are using the context context instances. Object name: 'ApplicationDbContext'.
All work with the database context is done using
try { using (var db = dbFactory()) { var customer = await db.Customers.Include(c => c.Identity) .SingleOrDefaultAsync(c => c.Identity.Id == userId.Value); if (requirement.Permissions <= customer?.ClientLevel) context.Succeed(requirement); } } catch (Exception ex) { logger.LogError(ex, "Permission check failed"); } My base is MySQL + ASPNETCORE + EFCORE.
So how to cook it?