Abp: Error: Cannot access a disposed object (DbContext in a background job)

Created on 22 Feb 2020  路  7Comments  路  Source: abpframework/abp

I'm using a background job in a CrudAppService derived class and CreateAsync method as below:
``` C#
public override async Task CreateAsync(ReservationCreateDto input)
{

        var entity = MapToEntity(input);
        var reservation = await this._reservationManager.InsertAsync(entity);

        // update crs inventory
        await this._backgroundJobManager.EnqueueAsync(new UpdateInventoryArgs { ReservationId = reservation.Id });

        var dto = MapToGetOutputDto(reservation);
        await this._reservationHub.SendReservationToUser(dto);
        return dto;

    }
and my background job class is:
```C#
    public class UpdateInventoryJob : BackgroundJob<UpdateInventoryArgs>, ITransientDependency
    {

        private readonly ICrsRemoteManager _crsRemoteManager; // It's a domain service
        public UpdateInventoryJob(ICrsRemoteManager crsRemoteManager)
        {
            this._crsRemoteManager = crsRemoteManager;
        }

        public override void Execute(UpdateInventoryArgs args)
        {
            _crsRemoteManager.UpdateCrsRoomsInventoryByReservation(reservationId: args.ReservationId);
        }
    }

In the CrsRemoteManager (a domain service) class I injected IReservationRepository in the constructor :
``` C#
public class CrsRemoteManager : ICrsRemoteManager
{
private readonly IReservationRepository _reservationRepository;
// ...
public CrsRemoteManager(

   //... some other injections
         IReservationRepository reservationRepository,
     )
    {
     //....
        this._reservationRepository = reservationRepository;

       //....
    }

public async Task UpdateCrsRoomsInventoryByReservation(int reservationId)
{
try
{

                var reservation = _reservationRepository.WithDetails().FirstOrDefault(q => q.Id == reservationId);  // here I get the Error

   //....

}

When background job executes, I get this error: 

Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'PmsCloudDbContext'.
```
What is the problem ? what I did wrong?

Most helpful comment

UpdateCrsRoomsInventoryByReservation is async.

Inherit AsyncBackgroundJob<UpdateInventoryArgs> instead and await that call in ExecuteAsync.

All 7 comments

Use UnitOfWorkAttribute

[UnitOfWork]
public override void Execute(UpdateInventoryArgs args)
{
     _crsRemoteManager.UpdateCrsRoomsInventoryByReservation(reservationId: args.ReservationId);
}

Use UnitOfWorkAttribute

[UnitOfWork]
public override void Execute(UpdateInventoryArgs args)
{
     _crsRemoteManager.UpdateCrsRoomsInventoryByReservation(reservationId: args.ReservationId);
}

I Used UnitOfWorkAttribute. The reservationRepository resolved properly but I have two repositories that injected in the UpdateCrsRoomsInventoryByReservation method. And now the roomTypeRepository throws this error:

Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.

This is my full constructor injection :

```C#
public CrsRemoteManager(
ISettingManager settingManager,
ILogger logger,
IRoomTypeRepository roomTypeRepository,
IReservationRepository reservationRepository,
IReportManager reportManager)
{
this._logger = logger;

        this._settingManager = settingManager;
        this._reportManager = reportManager;
        this._roomTypeRepository = roomTypeRepository;
        this._reservationRepository = reservationRepository;

        loadSettings().Wait();
        restClient = new RestClient(this.host);
    }

```

@inamvar Please provide error log

@inamvar Please provide error log

here the error log:

[10:21:22 ERR] Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.
System.ObjectDisposedException: Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.
   at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)
   at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Volo.Abp.Domain.Repositories.EntityFrameworkCore.EfCoreRepository`2.<.ctor>b__10_0()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at Volo.Abp.Domain.Repositories.EntityFrameworkCore.EfCoreRepository`2.get_AbpEntityOptions()
   at Volo.Abp.Domain.Repositories.EntityFrameworkCore.EfCoreRepository`2.WithDetails()
   at Castle.Proxies.Invocations.IReadOnlyRepository`1_WithDetails_24.InvokeMethodOnTarget()
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.DynamicProxy.AbstractInvocation.ProceedInfo.Invoke()
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedSynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
--- End of stack trace from previous location where exception was thrown ---
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.NoCoverage.RethrowHelper.Rethrow(Exception exception)
   at Castle.DynamicProxy.NoCoverage.RethrowHelper.RethrowInnerIfAggregate(Exception exception)
   at Castle.DynamicProxy.AsyncInterceptorBase.InterceptSynchronousResult[TResult](AsyncInterceptorBase me, IInvocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.IBasicRepository`1Proxy_12.WithDetails()
   at Dariksoft.PmsCloud.Crs.CrsRemoteManager.UpdateCrsRoomsInventoryByReservation(Int32 reservationId)

Can you reproduce this problem by start template? And upload the project to github @inamvar

UpdateCrsRoomsInventoryByReservation is async.

Inherit AsyncBackgroundJob<UpdateInventoryArgs> instead and await that call in ExecuteAsync.

UpdateCrsRoomsInventoryByReservation is async.

Inherit AsyncBackgroundJob<UpdateInventoryArgs> instead and await that call in ExecuteAsync.

@acjh @liangshiw
I changed it to AsyncBackgroundJob and it worked properly.
Thanks buddy 馃憤

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hikalkan picture hikalkan  路  3Comments

wocar picture wocar  路  3Comments

leonkosak picture leonkosak  路  3Comments

vfabregat picture vfabregat  路  3Comments

ChangYinShung picture ChangYinShung  路  3Comments