C# MVC4和x2B;Ninject+;石英-执行以下操作的正确方法是什么:

C# MVC4和x2B;Ninject+;石英-执行以下操作的正确方法是什么:,c#,entity-framework,asp.net-mvc-4,ninject,quartz.net,C#,Entity Framework,Asp.net Mvc 4,Ninject,Quartz.net,在我的解决方案中,我在主web项目中使用EF和repository模式以及Ninject来解决控制器依赖关系,我还有一个管理Quartz作业的作业项目-什么是将Ninject与Quartz链接以使EF工作的正确方法 我知道我需要实现自定义JobFactory,因此我在我的作业项目中创建了以下内容: public class NinjectJobFactory : IJobFactory { private readonly IKernel resolutionRoot; pub

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

我知道我需要实现自定义JobFactory,因此我在我的作业项目中创建了以下内容:

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 = "";
    }
}
为了初始化quartz作业,我执行以下操作:

  • 在Global.asax内部:我首先初始化我的NinjectResolver,然后将NinjectKernel作为参数传递给JobManager类
  • 然后在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();
     }
    
    public void Start()
    {
    isSchedulerFactory sf=新StdSchedulerFactory();
    isScheduler sched=sf.GetScheduler();
    sf.GetScheduler().JobFactory=新的NinjectJobFactory(ninjectKernel);
    DateTimeOffset运行时=DateBuilder.EvenMinuteDate(DateTime.UtcNow);
    DateTimeOffset startTime=DateBuilder.NextGivenSecondDate(null,10);
    IJobDetail job=JobBuilder.Create()
    .WithIdentity(“CheckIfAllSaleActionDataIsValid”,“HostessStatJobs”)
    .Build();
    job.JobDataMap.Add(“SiteUrl”,SiteUrl);
    ITrigger trigger=TriggerBuilder.Create()
    .WithIdentity(“CheckIfAllSaleActionDataIsValidTrigger”、“HostessStatJobTrigger”)
    .StartAt(startTime)
    .WithCronSchedule(“0 0/1 1/1*?*”)
    .Build();
    sched.ScheduleJob(作业,触发器);
    IJobDetail job2=JobBuilder.Create()
    .带有标识(“支票付款和分配角色”、“女主人工作”)
    .Build();
    job2.JobDataMap.Add(“commonMethods”,ninjectKernel.Get());
    ITrigger trigger2=TriggerBuilder.Create()
    .带有标识(“支票付款和分配角色触发器”、“HostessStatJobTriggers”)
    .StartAt(startTime)
    .WithCronSchedule(“0 0/1*1/1*?*”)
    .Build();
    调度作业(作业2,触发器2);
    sched.Start();
    }
    
  • 问题是NinjectJobFactory生成的每个对象的DbContext都是不同的,因此我不能使用EF(我得到:一个实体对象不能被IEntityChangeTracker的多个实例引用,这是可以理解的,因为我存储库中的每个对象都引用了不同的DbContext)

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

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

    问题是:

  • 我做错了什么
  • 如果这是因为我传递了我的NinjectKernel,那么在我的作业项目中创建不同的NinjectResolver会有帮助吗
  • 如果AD2是真的,那么为每个项目创建不同的IoC是明智的,还是我们应该只在真正必要的时候才这样做
  • 编辑:

    很抱歉,响应太晚,似乎InRequestScope实际上就是问题所在-我在QuartzJobs子项目中创建了单独的ninject内核,并且:

  • 当我使用InTransientScope时,我得到了与以前相同的行为,即:每个对象都有不同的DbContext
  • 当我使用InSingletonScope或InThreadScope时,它可以工作,每个对象都有一个DbContext,但是-DbContext不会在每次作业启动时都更改
  • 问题是-它不会破坏我的数据库吗?据我所知,建议对每个用户请求使用新的DbContext,以避免数据库死锁-如果我错了,请纠正我,但对于Quartz作业项目,这不是必需的?我的意思是-这个项目总是使用单连接,所以它不应该使数据库死锁


    我说得对吗?如果不是-每次运行作业时注入不同DbContext的正确方法是什么?InRequestScope在MVC项目之外不起作用…

    作业应该使用哪个
    DbContext
    实例?由于quartz会在稍后时间安排作业,因此在该时间点没有“有效”请求。所以我猜绑定
    DbContext
    .InRequestScope()
    不能正常工作。您需要一些其他方法来控制计划作业的
    DbContext
    的生命周期。@BatteryBackupUnit:很抱歉我的回复太晚-请参阅我的编辑。