ASP.NET nHibernate + Quartz.NET + Unity

时间:2015-03-12 05:34:08

标签: asp.net-mvc nhibernate fluent-nhibernate unity-container quartz.net

我正在为ASP.NET MVC开发一个Web应用程序。基于nHibernate使用与数据存储库交互。存储库通过Unity实例化。根据请求存储已解析的ISession。

现在我需要添加项目抓取工具在后台执行定期计划任务。实现一个爬虫选择Quartz.NET。项目可以有几个不同的步行者,同时通过存储库与数据库交互,如果匹配任务的执行。

问题是爬虫必须创建另一个会话,因为它基于请求解决方案不起作用(没有Web请求)。它实现了一个解决方案,我在其中注册了两个不同的ISession实现,但它不起作用。代码示例如下。

出现以下问题:

  1. 这是解决问题的正确方向吗?
  2. 如何正确实施?
  3. 这会不会导致两个爬虫尝试写入数据库,导致错误?
  4. 代码:

    public class DatabaseRepositoriesRegistration : IUnityRegistration
    {
        public void Register(IUnityContainer container)
        {
            // web
            var connectionString = WebConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
            SessionManager.ConnectionString = connectionString;
            container.RegisterType<ISession>(new HierarchicalLifetimeManager(),
                new InjectionFactory(c => SessionManager.CurrentSession)
               );
    
            container.RegisterType<IUnitOfWork, NHibernateUnitOfWork>(new HierarchicalLifetimeManager());
            container.RegisterType(typeof(IRepository<>), typeof(NHibernateRepository<>), new HierarchicalLifetimeManager());
    
            // externals
    
            container.RegisterType<ISession>("ext", new HierarchicalLifetimeManager(), new InjectionFactory(c =>
            {
                var config = Fluently.Configure().
                Database(
                    MsSqlConfiguration
                        .MsSql2008
                        .ConnectionString(connectionString)
                        .UseReflectionOptimizer()
                        )
                .Mappings(m => m.FluentMappings.AddFromAssemblyOf<MappingBeacon>())
                .BuildConfiguration();
    
                var sessionFactory = config.BuildSessionFactory();
                return sessionFactory.OpenSession();
            }));
    
            container.RegisterType(typeof(IRepository<>), typeof(NHibernateRepository<>), "ext", new HierarchicalLifetimeManager(), new InjectionConstructor(new ResolvedParameter<ISession>("ext")));
        }
    }
    

    public class SchedulerTask : MvcStartupTaskBase
    {
        private readonly IUnityContainer container;
    
        public SchedulerTask(IUnityContainer container)
        {
            this.container = container;
        }
    
        public override void Run()
        {
            var scheduler = container.Resolve<IScheduler>();
            scheduler.JobFactory = new UnityJobFactory(container);
            scheduler.Start();
    
            var job = JobBuilder.Create<UploadConvertionTask>().Build();
    
            var trigger = TriggerBuilder.Create()
                .WithDailyTimeIntervalSchedule
                  (s =>
                     s.WithIntervalInMinutes(1)
                    .OnEveryDay()
                    .StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(0, 0))
                  )
                .Build();
    
            scheduler.ScheduleJob(job, trigger);
        }
    
        public class UnityJobFactory : IJobFactory
        {
            private readonly IUnityContainer container;
    
            public UnityJobFactory(IUnityContainer container)
            {
                this.container = container;
            }
    
            public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
            {
                return (IJob)container.Resolve(bundle.JobDetail.JobType, "ext");
            }
    
            public void ReturnJob(IJob job)
            {
            }
        }
    }
    

    public class UploadConvertionTask: IJob
    {
        public UploadConvertionTask(IRepository<Upload> uploadRepositiory) {
            // for repository session is closed!
        }
    
        public void Execute(IJobExecutionContext context)
        {
    
        }
    }
    

1 个答案:

答案 0 :(得分:1)

您的调度程序在run方法中设置为局部变量。它需要是一个足以让调度程序运行任务的变量。在不知道整个项目的细节的情况下,您应该将调度程序设置为在应用程序启动时创建的单例。然后,在您安排作业时引用此单例实例。

理想情况下,您的调度程序应作为单独的长期运行服务运行,例如Windows服务。