检测自托管Web Api中的上下文

时间:2014-11-19 14:24:58

标签: c# nhibernate asp.net-web-api owin quartz.net

在我目前的项目中,我有一个定期运行任务的Windows服务(TopShelf / Quartz.net)。我想使用OWIN中提供的自托管功能将其添加到Windows服务,而不是为Web服务创建单独的项目。这也增加了不需要在IIS中部署的好处。

当我要实施我的数据访问层(DAL)时,我会遇到问题。

我的所有数据库操作都在UnitOfWork中完成,该UnitOfWork存储在请求状态中,最后有一个提交/回滚。上下文确定UnitOfWork的生命周期(请求状态)。在控制台应用程序中,我将使用PerThreadRequest状态。在Web环境中,我有一个PerHttpRequestState。这意味着UnitOfWork的范围是每个线程或每个HttpRequest。

在我目前的项目中,我有混合控制台(Quartz作业)和web(web api调用)。这些都需要使用DAL,但不能使用与其他上下文相同的请求状态。

我可以手动解决这个问题。当使用来自quartz作业的DAL时,让它使用PerThreadRequestState,当使用来自web api调用的DAL时,使用PerHttpRequestState,但这是一个混乱的解决方案。 使用DAL时,它应检测到它正在运行并做出相应的反应。

但我怎样才能检测上下文?

1 个答案:

答案 0 :(得分:0)

我建议使用Castle Windsor这样的东西(虽然原理与其他IOC / DI框架相同)

if(HttpRuntime.AppDomainAppId != null) //it's a web app
{
    container.Register(
         Component.For<IUnitOfWork>().ImplementedBy<PerHttpRequestState>());
}
else //it's a windows app
{
    container.Register(
         Component.For<IUnitOfWork>().ImplementedBy<PerThreadRequestState>());
}

话虽如此,在线程生活方式中使用UoW仍有一些注意事项:

  • 首先,您必须确保您的UoW是线程安全的(如果两个或多个作业最终同时访问UoW会发生什么?)
  • 更重要的是,Quartz.NET在内部使用ThreadPool,因此每次启动作业时都不一定会创建新的线程,而是重用现有的线程。这可能导致泄漏;您的UoW可以在作业之间事实上共享。您可能想要的是使用自定义 PerQuartzJob 生活方式。

然而,这两者都取决于您打算将石英服务用于何种用途。如果你没有很多长期运行的,可能重叠的CRUD工作,那么它们就不那么重要了。