1

I'm using HotChocolate Graphql in .net core 6 and it suggests using PooledDbContext, however, now I need to create a brackground service, but I can't inject the Db Context In the Background Services, it throws this exeption:

Unhandled exception. System.InvalidOperationException: No service for type 'DedicatedServers.Data.ApplicationDbContext' has been registered.
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at DedicatedServers_API.Services.BackgroundServices.CreateInstancesWhenOrdersArePaid.DoInjecting() in C:\Users\bardhyliis\Desktop\DedicatedServer\DedicatedServers_API\Services\BackgroundServices\CreateInstancesWhenOrdersArePaid.cs:line 29
   at DedicatedServers_API.Services.BackgroundServices.CreateInstancesWhenOrdersArePaid.ExecuteAsync(CancellationToken stoppingToken) in C:....API\Services\BackgroundServices\CreateInstancesWhenOrdersArePaid.cs:line 38
   at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
   at Microsoft.AspNetCore.Builder.WebApplication.Run(String url)
   at Program.<Main>$(String[] args) in C:....\Program.cs:line 214
watch : Exited with error code -532462766
watch : Waiting for a file to change before restarting dotnet...

"Paths edited.!!"

Program.cs :

builder.Services.AddPooledDbContextFactory<ApplicationDbContext>(options =>
{
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("DefaultConnection"),
        options => options.EnableRetryOnFailure()
    );
});

#region Background Services
builder.Services.AddHostedService<CreateInstancesWhenOrdersArePaid>();
builder.Services.AddHostedService<FixPaidOrdersWithNoInstance>();
builder.Services.AddHostedService<CancelUnpaidOrders>();
builder.Services.AddHostedService<PayMonthlyDue>();
builder.Services.AddHostedService<SendInfoAboutDuePayment>();
builder.Services.AddHostedService<CheckMonthlyDuePaymentsAreSettled>();
#endregion

One of the Background Services, all inject of them services in the same way:

private readonly IServiceScopeFactory scopeFactory;
private ApplicationDbContext context = null!;
private BraintreeService braintreeService = null!;
private EmailService emailService = null!;
private ContaboInstanceService contaboInstanceService = null!;

public CheckMonthlyDuePaymentsAreSettled(IServiceScopeFactory scopeFactory)
{
    this.scopeFactory = scopeFactory;
}

public void DoInjecting(){
    using (var scope = scopeFactory.CreateScope())
    {
        context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
        braintreeService = scope.ServiceProvider.GetRequiredService<BraintreeService>();
        emailService = scope.ServiceProvider.GetRequiredService<EmailService>();
        contaboInstanceService = scope.ServiceProvider.GetRequiredService<ContaboInstanceService>();
    }
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    DoInjecting();
}

I've tried adding the ApplicationDbContext as As a singleton or transient, It doesn't work either, It returns this error:

Entity Framework Core 6.0.5 initialized 'ApplicationDbContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer:6.0.5' with options: MaxPoolSize=1024
fail: Microsoft.EntityFrameworkCore.Query[10100]
      An exception occurred while iterating over the results of a query for context type 'DedicatedServers.Data.ApplicationDbContext'.
      System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
         at Microsoft.EntityFrameworkCore.Infrastructure.Internal.ConcurrencyDetector.EnterCriticalSection()
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
      System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
         at Microsoft.EntityFrameworkCore.Infrastructure.Internal.ConcurrencyDetector.EnterCriticalSection()
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
fail: Microsoft.EntityFrameworkCore.Database.Connection[20004]
      An error occurred using the connection to database 'DedicatedServer' on server 'localhost\SQLEXPRESS'.
Unhandled exception. fail: Microsoft.EntityFrameworkCore.Query[10100]
      An exception occurred while iterating over the results of a query for context type 'DedicatedServers.Data.ApplicationDbContext'.
      System.AggregateException: An error occurred while writing to logger(s). (Cannot access a disposed object.
      Object name: 'EventLogInternal'.)
       ---> System.ObjectDisposedException: Cannot access a disposed object.
      Object name: 'EventLogInternal'.
         at System.Diagnostics.EventLogInternal.OpenForWrite(String currentMachineName)
         at System.Diagnostics.EventLogInternal.InternalWriteEvent(UInt32 eventID, UInt16 category, EventLogEntryType type, String[] strings, Byte[] rawData, String currentMachineName)
         at System.Diagnostics.EventLogInternal.WriteEvent(EventInstance instance, Byte[] data, Object[] values)
         at System.Diagnostics.EventLog.WriteEvent(EventInstance instance, Object[] values)
         at Microsoft.Extensions.Logging.EventLog.WindowsEventLog.WriteEntry(String message, EventLogEntryType type, Int32 eventID, Int16 category)
         at Microsoft.Extensions.Logging.EventLog.EventLogLogger.WriteMessage(String message, EventLogEntryType eventLogEntryType, Int32 eventId)
         at Microsoft.Extensions.Logging.EventLog.EventLogLogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
         at Microsoft.Extensions.Logging.Logger.<Log>g__LoggerLog|12_0[TState](LogLevel logLevel, EventId eventId, ILogger logger, Exception exception, Func`3 formatter, List`1& exceptions, TState& state)
         --- End of inner exception stack trace ---
         at Microsoft.Extensions.Logging.Logger.ThrowLoggingError(List`1 exceptions)
         at Microsoft.Extensions.Logging.Logger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
         at Microsoft.Extensions.Logging.LoggerMessage.<>c__DisplayClass12_0`2.<Define>g__Log|0(ILogger logger, T1 arg1, T2 arg2, Exception exception)
         at Microsoft.Extensions.Logging.LoggerMessage.<>c__DisplayClass12_0`2.<Define>b__1(ILogger logger, T1 arg1, T2 arg2, Exception exception)
         at Microsoft.EntityFrameworkCore.Diagnostics.EventDefinition`2.Log[TLoggerCategory](IDiagnosticsLogger`1 logger, TParam1 arg1, TParam2 arg2)
         at Microsoft.EntityFrameworkCore.Diagnostics.Internal.RelationalConnectionDiagnosticsLogger.LogConnectionError(IRelationalConnection connection, EventDefinition`2 
definition)
         at Microsoft.EntityFrameworkCore.Diagnostics.Internal.RelationalConnectionDiagnosticsLogger.ConnectionErrorAsync(IRelationalConnection connection, Exception exception, DateTimeOffset startTime, TimeSpan duration, Boolean logErrorAsDebug, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
         at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.<>c__DisplayClass33_0`2.<<ExecuteAsync>b__0>d.MoveNext()
      --- End of stack trace from previous location ---
         at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func`4 operation, Func`4 verifySucceeded, TState state, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func`4 operation, Func`4 verifySucceeded, TState state, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
      System.AggregateException: An error occurred while writing to logger(s). (Cannot access a disposed object.
      Object name: 'EventLogInternal'.)
       ---> System.ObjectDisposedException: Cannot access a disposed object.
      Object name: 'EventLogInternal'.
         at System.Diagnostics.EventLogInternal.OpenForWrite(String currentMachineName)
         at System.Diagnostics.EventLogInternal.InternalWriteEvent(UInt32 eventID, UInt16 category, EventLogEntryType type, String[] strings, Byte[] rawData, String currentMachineName)
         at System.Diagnostics.EventLogInternal.WriteEvent(EventInstance instance, Byte[] data, Object[] values)
         at System.Diagnostics.EventLog.WriteEvent(EventInstance instance, Object[] values)
         at Microsoft.Extensions.Logging.EventLog.WindowsEventLog.WriteEntry(String message, EventLogEntryType type, Int32 eventID, Int16 category)
         at Microsoft.Extensions.Logging.EventLog.EventLogLogger.WriteMessage(String message, EventLogEntryType eventLogEntryType, Int32 eventId)
         at Microsoft.Extensions.Logging.EventLog.EventLogLogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)       
         at Microsoft.Extensions.Logging.Logger.<Log>g__LoggerLog|12_0[TState](LogLevel logLevel, EventId eventId, ILogger logger, Exception exception, Func`3 formatter, List`1& exceptions, TState& state)
         --- End of inner exception stack trace ---
burnsi
  • 6,194
  • 13
  • 17
  • 27
  • The code you posted doesn't execute EF code. What do those services do? Are they trying to use the same DbContext in different threads? Your `DoInject()` method creates those objects and *immediately* disposes the scope which also disposes the generated objects and any other scoped services like `ILogger<>`s . If any async code tries to log something it would get an ObjectDisposedException – Panagiotis Kanavos Jul 04 '22 at 12:48
  • 1
    `DoInjecting()` actually creates scoped classes and disposes them on exit. – Svyatoslav Danyliv Jul 04 '22 at 12:50
  • `DoInjecting()` alone is enough to cause the `ObjectDisposedException`s. What do those services do? Do they start any async tasks? Call Task.Run? – Panagiotis Kanavos Jul 04 '22 at 12:52
  • i had a similar case, i used IServiceProvider directly was and the issue resolved. to check this hypothesis you can resolve something else before context, if the other service did not resolve successfully then the problem is with the IScope itself. – Hadi Bazmi Jul 04 '22 at 12:54
  • @PanagiotisKanavos It's just as you said, I've been disposing the scope without knowing what I was doing, thank you very much. I fixed It, I ended up injecting the ApplicationDbContext as a ScopedService and fixing the problem of disposing the scopes by removing the using statement. – bardhyl sllamniku Jul 04 '22 at 14:06
  • what the heck. No. You want to dispose the scope, but you want to do it when all the work is done. You want to use "using" but inside the code block making use of the services. That method itself does not make much sense. – Pablo Recalde Jul 04 '22 at 15:50
  • Yes of course, I thought it was implied. – bardhyl sllamniku Jul 04 '22 at 15:54

0 Answers0