【发布时间】:2013-08-07 05:00:12
【问题描述】:
我正在使用quartz 和nhibernate,但遇到了问题。通常我会在网络请求完成时关闭所有的休眠会话,但我有一个在应用程序启动时启动的调度程序,我需要传入一个我认为永远不应该关闭的休眠会话。
我不确定该怎么做。
忍者
public class NhibernateSessionFactoryProvider : Provider<ISessionFactory>
{
protected override ISessionFactory CreateInstance(IContext context)
{
var sessionFactory = new NhibernateSessionFactory();
return sessionFactory.GetSessionFactory();
}
}
public class NhibernateModule : NinjectModule
{
public override void Load()
{
Bind<ISessionFactory>().ToProvider<NhibernateSessionFactoryProvider>().InSingletonScope();
Bind<ISession>().ToMethod(context => context.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope();
}
}
全球.aspx
protected void Application_Start()
{
// Hook our DI stuff when application starts
IKernel kernel = SetupDependencyInjection();
// get the reminder service HERE IS WHERE THE PROBLEMS START
IScheduledRemindersService scheduledRemindersService = kernel.Get<IScheduledRemindersService>();
scheduledRemindersService.StartTaskRemindersSchedule();
RegisterMaps.Register();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
public IKernel SetupDependencyInjection()
{
IKernel kernel = CreateKernel();
// Tell ASP.NET MVC 3 to use our Ninject DI Container
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
return kernel;
}
protected IKernel CreateKernel()
{
var modules = new INinjectModule[]
{
new NhibernateModule(),
new ServiceModule(),
new RepoModule()
};
return new StandardKernel(modules);
}
// 导致我出现问题的服务。 Ninject 将绑定reminderRepo 并给它一个nihbernate 会话。
private readonly IReminderRepo reminderRepo;
private readonly ISchedulerFactory schedulerFactory;
public ScheduledRemindersService(IReminderRepo reminderRepo)
{
this.reminderRepo = reminderRepo;
schedulerFactory = new StdSchedulerFactory();
}
public void StartTaskRemindersSchedule()
{
IScheduler scheduler = schedulerFactory.GetScheduler();
scheduler.Start();
JobDetail jobDetail = new JobDetail("TaskRemindersJob",null,typeof(TaskReminderJob));
jobDetail.JobDataMap["reminderRepo"] = reminderRepo;
DateTime evenMinuteDate = TriggerUtils.GetEvenMinuteDate(DateTime.UtcNow);
SimpleTrigger trigger = new SimpleTrigger("TaskRemindersTrigger", null,
DateTime.UtcNow,
null,
SimpleTrigger.RepeatIndefinitely,
TimeSpan.FromMinutes(1));
scheduler.ScheduleJob(jobDetail, trigger);
}
所以我需要像上面那样将reminderRepo传递给工作
jobDetail.JobDataMap["reminderRepo"] = reminderRepo;
这是您将某些东西传递给工作的唯一方法。每次执行计划时,都会重新创建一个作业,我假设它使用与我发送的相同的reminderRepo。
我在服务层中的代码永远不会再次执行,当然应用程序也会启动(除非我重新部署站点)
工作
public class TaskReminderJob : IJob
{
public void Execute(JobExecutionContext context)
{
JobDataMap dataMap = context.JobDetail.JobDataMap;
ReminderRepo reminderRepo = dataMap["reminderRepo"] as ReminderRepo;
if (context.ScheduledFireTimeUtc.HasValue && context.NextFireTimeUtc.HasValue && reminderRepo != null)
{
DateTime start = context.ScheduledFireTimeUtc.Value;
DateTime end = context.NextFireTimeUtc.Value;
List<PersonalTaskReminder> personalTaskReminders = reminderRepo.GetPersonalTaskReminders(start, end);
if (personalTaskReminders.Count > 0)
{
reminderRepo.DeletePersonalTaskReminders(personalTaskReminders.Select(x => x.ReminderId).ToList());
}
}
}
提醒回购。 (当这个 repo 被实例化时,应该给出一个会话,该会话将一直持续到请求结束)
public class ReminderRepo : IReminderRepo
{
private readonly ISession session;
public ReminderRepo(ISession session)
{
this.session = session;
}
public List<PersonalTaskReminder> GetPersonalTaskReminders(DateTime start, DateTime end)
{
List<PersonalTaskReminder> personalTaskReminders = session.Query<PersonalTaskReminder>().Where(x => x.DateToBeSent <= start && x.DateToBeSent <= end).ToList();
return personalTaskReminders;
}
public void DeletePersonalTaskReminders(List<int> reminderId)
{
const string query = "DELETE FROM PersonalTaskReminder WHERE ReminderId IN (:reminderId)";
session.CreateQuery(query).SetParameterList("reminderId", reminderId).ExecuteUpdate();
}
public void Commit()
{
using (ITransaction transaction = session.BeginTransaction())
{
transaction.Commit();
}
}
}
所以我需要一些方法来让会话保持活跃以进行提醒。我所有其他回购的所有其他会话都应该像我现在拥有的那样。似乎只有这一个需要永生。
编辑
我每次都尝试获取一个新会话,因此我传递了 IsessionFactory。可能不是 100% 最好,但这是我弄清楚如何获得一些新会话的唯一方法。
但是我不知道我的会话是否仍然通过 ninject 关闭,因为我现在手动传递会话。我现在想,但无法验证。
**private readonly ISessionFactory sessionFactory;**
private readonly ISchedulerFactory schedulerFactory;
public ScheduledRemindersService(ISessionFactory sessionFactory)
{
**this.sessionFactory = sessionFactory;**
schedulerFactory = new StdSchedulerFactory();
}
public void StartTaskRemindersSchedule()
{
IScheduler scheduler = schedulerFactory.GetScheduler();
scheduler.Start();
JobDetail jobDetail = new JobDetail("TaskRemindersJob",null,typeof(TaskReminderJob));
**jobDetail.JobDataMap["reminderRepo"] = sessionFactory;**
DateTime evenMinuteDate = TriggerUtils.GetEvenMinuteDate(DateTime.UtcNow);
SimpleTrigger trigger = new SimpleTrigger("TaskRemindersTrigger", null,
DateTime.UtcNow,
null,
SimpleTrigger.RepeatIndefinitely,
TimeSpan.FromMinutes(1));
scheduler.ScheduleJob(jobDetail, trigger);
}
所以我的 global.aspx 是相同的,但是由于 ninject 现在看到“ScheduledRemindersService”现在接受了一个休眠会话工厂,它为我绑定了一个我可以使用的工厂。
然后我把它传递给工作。
public void Execute(JobExecutionContext context)
{
JobDataMap dataMap = context.JobDetail.JobDataMap;
ISessionFactory sessionFactory = dataMap["reminderRepo"] as ISessionFactory;
if (sessionFactory != null)
{
ISession openSession = sessionFactory.OpenSession();
ReminderRepo reminderRepo = new ReminderRepo(openSession);
}
}
然后我将它传递到我的 ReminderRepo 中,所以我猜它会忽略来自 ninject 的自动会话绑定,但我不能 100% 确定,因此我不确定我的会话是否正在关闭。
【问题讨论】:
标签: asp.net-mvc nhibernate quartz.net