无法在 ABP 中的 Hangfire 循环作业上访问处置对象(在 DbContext 上)错误

Cannot access a disposed object (on DbContext) error on Hangfire recurrent job in ABP

我正在尝试在应用程序启动时设置 Hangfire 循环作业,但在作业中如果我尝试使用注入 IRepository,它会在尝试执行时给出与 DbContext 相关的错误查询:

System.ObjectDisposedException
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: 'WsApplicationDbContext'.

System.ObjectDisposedException: 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: 'WsApplicationDbContext'.
   at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityType()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityQueryable()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Linq.IQueryable.get_Provider()
   at System.Linq.Queryable.Select[TSource,TResult](IQueryable`1 source, Expression`1 selector)
   at WsApplication.RecurringJobs.Jobs.ContainerIsBookedOffHireRecurringJob.TestJob() in C:\Projects\boxman\aspnet-core\src\WsApplication.Application\RecurringJobs\Jobs\ContainerIsBookedOffHireRecurringJob.cs:line 26

我已经完全按照 ABP documentation 中的描述注册了 Hangfire。 此外,我正在 <ApplicationName>.Web.Core 模块中像这样注册我的工作:

public override void PostInitialize()
{
    ...

    // set up recurring background jobs
    var job = IocManager.Resolve<ContainerIsBookedOffHireRecurringJob>();
    RecurringJob.AddOrUpdate<ContainerIsBookedOffHireRecurringJob>("TestJobWithRepository", j => j.TestJob(), Cron.Daily);
}

我的工作方法只是尝试使用注入的存储库进行查询。

public class ContainerIsBookedOffHireRecurringJob : BaseRecurringJob
{
    private readonly IRepository<ContractLineMovement, int> _contractLineMovementRepository;

    public ContainerIsBookedOffHireRecurringJob(
        IIocResolver iocResolver,
        IRepository<ContractLineMovement, int> contractLineMovementRepository
    ) : base(iocResolver)
    {
        _contractLineMovementRepository = contractLineMovementRepository;
    }

    public void TestJob()
    {
        var testQuery = from contractLineMovement in _contractLineMovementRepository.GetAll()
                        select contractLineMovement;

        testQuery.ToList().ForEach(t =>
        {
            Logger.Debug("Fetched ContractLineMovement ID: " + t.Id + " Type: " + t.ContractWorkFlowEventId);
        });
    }
}

我已经设法通过直接在 BaseRecurringJob 中解析 WsApplicationDbContext 来解决这个问题,但我不太喜欢那个解决方案。我不明白为什么它不能简单地与依赖注入一起使用。 是因为我在启动时注册它们吗?我需要某种自定义 Job Activator 吗?

如有任何帮助,我们将不胜感激。

添加 [UnitOfWork] 属性并使其成为 virtual 方法:

[UnitOfWork]
public virtual void TestJob()
{
    ...
}

参见:UnitOfWork Attribute Restrictions

You can use UnitOfWork attribute for:

  • All public or public virtual methods for classes that are used over an interface (Like an application service used over a service interface).
  • All public virtual methods for self-injected classes (Like MVC Controllers and Web API Controllers).
  • All protected virtual methods.