MVC4 + Ninject + Quartz - 执行以下操作的正确方法是什么:

时间:2014-04-30 09:13:05

标签: c# entity-framework asp.net-mvc-4 ninject quartz.net

在我的解决方案中,我使用EF与存储库模式和我的主要Web项目中的Ninject来解决控制器依赖关系,我还有一个管理Quartz作业的Job项目 - 将Ninject与Quartz链接的正确方法是什么,以便EF将工作?

我知道我需要实现自定义JobFactory,所以我在Job项目中创建了以下内容:

public class NinjectJobFactory : IJobFactory
{
    private readonly IKernel resolutionRoot;

    public NinjectJobFactory(IKernel resolutionRoot)
    {
        this.resolutionRoot = resolutionRoot;
    }

    public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
    {
        return (IJob)this.resolutionRoot.Get(bundle.JobDetail.JobType);
    }

    public void ReturnJob(IJob job)
    {
        string dud = "";
    }
}

为了初始化石英作业,我执行以下操作:

  1. Inside Global.asax:我首先初始化我的NinjectResolver,然后将NinjectKernel作为参数传递给JobManager类。
  2. 然后在JobManager中,我添加作业并运行这样的调度程序:

    public void Start()
    {
        ISchedulerFactory sf = new StdSchedulerFactory();
        IScheduler sched = sf.GetScheduler();
        sf.GetScheduler().JobFactory = new NinjectJobFactory(ninjectKernel);
    
        DateTimeOffset runTime = DateBuilder.EvenMinuteDate(DateTime.UtcNow);
        DateTimeOffset startTime = DateBuilder.NextGivenSecondDate(null, 10);
    
        IJobDetail job = JobBuilder.Create<CheckIfAllSaleActionDataIsValid>()
     .WithIdentity("CheckIfAllSaleActionDataIsValid", "HostessStatJobs")
    .Build();
    
    job.JobDataMap.Add("SiteUrl", SiteUrl);
    
    ITrigger trigger = TriggerBuilder.Create()
    .WithIdentity("CheckIfAllSaleActionDataIsValidTrigger", "HostessStatJobTriggers")
    .StartAt(startTime)
    .WithCronSchedule("0 0 0/1 1/1 * ? *")
    .Build();
    
    sched.ScheduleJob(job, trigger);
    
    IJobDetail job2 = JobBuilder.Create<CheckPaymentAndAssigneRoles>()
    .WithIdentity("CheckPaymentAndAssigneRoles", "HostessStatJobs")
    .Build();
    
    job2.JobDataMap.Add("commonMethods", ninjectKernel.Get<CommonMethods>());
    
    ITrigger trigger2 = TriggerBuilder.Create()
    .WithIdentity("CheckPaymentAndAssigneRolesTrigger", "HostessStatJobTriggers")
    .StartAt(startTime)
    .WithCronSchedule("0 0/1 * 1/1 * ? *")
    .Build();
    
         sched.ScheduleJob(job2, trigger2);
    
         sched.Start();
     }
    
  3. 问题是由NinjectJobFactory生成的每个对象的DbContext是不同的,因此我不能使用EF(我得到:实体对象不能被IEntityChangeTracker的多个实例引用,这是可以理解的我的存储库中的每个对象都引用了不同的DbContext)。

    奇怪的是 - 如果我手动调用 NinjectKernel.Get(); - 例如 - 在Global.asax中我可以清楚地看到单个上下文被传递 - 应该是这样。

    我的上下文在我的Ninjectresolver中绑定如下: ninjectKernel.Bind()。ToSelf()。InRequestScope(); - 这可能是问题吗?

    问题是:

    1. 我做错了什么?
    2. 如果这是因为我传递了我的NinjectKernel - 会在我的Job项目帮助中创建不同的NinjectResolver吗?
    3. 如果AD2为真 - 建议为每个项目创建不同的IoC,还是应该在真正需要时才这样做?
    4. 编辑:

      对于迟到的回复感到抱歉,看起来InRequestScope实际上是问题 - 我在QuartzJobs子项目中创建了单独的ninject内核,并且:

      1. 当我使用InTransientScope时 - 我得到了与以前相同的行为,即:每个对象都有不同的DbContext。
      2. 当我使用InSingletonScope或InThreadScope时 - 它有效,我为每个对象都有单个DbContext,但是 - 每次作业开始时DbContext都不会改变。
      3. 问题是 - 它不会破坏我的数据库吗?据我了解,建议为每个用户请求使用新的DbContext以避免数据库死锁 - 如果我错了就纠正我,但是对于Quartz作业项目来说没有必要吗?我的意思是 - 这个项目总是使用单一连接,所以它不应该死锁数据库吗?

        我说错了吗?如果不是 - 每次运行Job时注入不同DbContext的正确方法是什么? InRequestScope不能在MVC项目之外工作......

0 个答案:

没有答案