【问题标题】:ASP.NET nHibernate+Quartz.NET+UnityASP.NET nHibernate+Quartz.NET+Unity
【发布时间】:2015-03-20 22:48:10
【问题描述】:

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

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

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

出现以下问题:

  1. 这是解决问题的正确方向吗?
  2. 如何正确实现?
  3. 这种做法会不会导致两个爬虫试图写入数据库,导致出错?

代码:

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)
    {

    }
}

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      相关资源
      最近更新 更多