Base solution for your next web application
Open Closed

Getting exception "cannot access a disposed object" #4203


User avatar
0
Ricavir created

Hi,

I'm implementing a background worker class to schedule some tasks automatically. I took as code example the class "SubscriptionExpirationCheckWorker" on MultiTenancy namespace.

I'm able to search for tenants

var tenantsForEventSchedule = _tenantRepository.GetAllList(tenant => tenant.IsActive);

and also to get some tenant settings.

But when I try to search for other entities, an exception is raised with message "cannot access a disposed object" relative to the db context. The system try to access the database but the connection ha been disposed before.

I've read aspnetboilerplate documentation about UnitOfWork ; therefore, I've added [UnitOfWork] attribute before DoWork method I still have the same exception.

How can I fix this ?

Here is an extract of the code :

public class EventSchedulerWorker : PeriodicBackgroundWorkerBase, ISingletonDependency
    {
        private const int CheckPeriodAsMilliseconds = 1 * 60 * 60 * 100; // demo 6 minutes

        private readonly IRepository<Tenant> _tenantRepository;
        private readonly IRepository<ContractSchedule, long> _contractScheduleRepository;
        private readonly TenantManager _tenantManager;
        private readonly IAppNotifier _appNotifier;

        public EventSchedulerWorker(
            AbpTimer timer,
            IRepository<Tenant> tenantRepository,
            IRepository<ContractSchedule, long> contractScheduleRepository,
            TenantManager tenantManager,
            IAppNotifier appNotifier)
            : base(timer)
        {
            _tenantRepository = tenantRepository;
            _contractScheduleRepository = contractScheduleRepository;
            _tenantManager = tenantManager;
            _appNotifier = appNotifier;

            Timer.Period = CheckPeriodAsMilliseconds;
            Timer.RunOnStart = true;

            LocalizationSourceName = LogisavConsts.LocalizationSourceName;
        }

        [UnitOfWork]
        protected override async void DoWork()
        {
            var tenantsForEventSchedule = _tenantRepository.GetAllList(tenant => tenant.IsActive);

            foreach (var tenant in tenantsForEventSchedule)
            {
                try
                {
                    if (await SettingManager.GetSettingValueForTenantAsync<bool>(AppSettings.TenantEvent.Scheduler_Activated, tenant.Id) == true)
                    {
                        //define period to search contracts
                        var today = Clock.Now.Date;
                        int dayCountBeforeEventCreation = await SettingManager.GetSettingValueForTenantAsync<int>(AppSettings.TenantEvent.Scheduler_DayCount_BeforeEventCreation, tenant.Id);
                        var startDate = today.AddDays(-dayCountBeforeEventCreation);
                        bool includeSuspendedContracts = await SettingManager.GetSettingValueForTenantAsync<bool>(AppSettings.TenantEvent.Scheduler_SuspendedContractIncluded, tenant.Id);                        

                        var contractsFound = _contractScheduleRepository
                            .GetAll()
                            .Include(c => c.Contract)
                            .Where(cs => cs.Contract.IsActive == true)
                            .WhereIf(!includeSuspendedContracts, cs => cs.Contract.IsSuspended == false)
                            .Where(cs => cs.ScheduleDate >= startDate && cs.ScheduleDate <= today)
                            .ToList();

             >>>>>>>>>>>> EXCEPTION HERE : "cannot access a disposed object"

4 Answer(s)
  • User Avatar
    0
    aaron created
    Support Team

    You cannot modify the method signature to be async as DoWork is called synchronously.

    Wrap your await method calls in AsyncHelper.RunSync(() => AsyncMethod(...)) like this:

    if (AsyncHelper.RunSync(() => SettingManager.GetSettingValueForTenantAsync<bool>(...)))
    {
        // ...
    }
    
  • User Avatar
    0
    Ricavir created

    Ok, tks for your clarification @aaron

  • User Avatar
    0
    rafalpiotrowski created

    fot me the AsyncHelper.RunSync does not help

    did this help you?

  • User Avatar
    0
    rafalpiotrowski created

    the following solved the problems

    using (var uow = UnitOfWorkManager.Begin()) { ... uow.Complete(); }