我正在重新审视我为使 StructureMap 与每个 Http 的 UoW 和每个石英作业的 UoW 一起工作所做的工作,我决定在这里分享我的解决方案。
所以我的想法是,我想在有 http 上下文时使用 StructureMap Hybrid 范围来获取 UoW 的实例,并且在没有 http 上下文时(例如触发石英作业时)还为每个线程获取不同的 UoW 实例)。像这样:
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<UnitOfWork>();
http 的 UoW 运行良好。问题是每个线程的 UoW。
这就是发生的事情。当 quratz 作业触发时,它会从线程池中拉出一个线程并开始使用该线程执行作业。当工作开始时,我要求 UoW。 StructureMap 在本地存储下查找该线程以返回 UoW,但因为它找不到任何它实例化一个并将其保存在线程的本地存储下。我得到了 UoW,然后执行 Begin、Commit、Dispose,一切都很好。
当从线程池中拉出线程时会出现问题,该线程池之前用于触发作业(并使用 UoW)。在这里,当您请求 UoW 时,StructureMap 会在缓存(线程本地存储)中查找并找到 UoW 并将其返回给您。但问题是 UoW 被处理掉了!
因此,我们不能真正将每个线程的 UoW 用于石英作业,因为线程本身没有被释放,并且它们保存旧的缓存释放的 UoW。 线程的生命周期基本上与石英作业的生命周期不匹配。这就是我为石英作业创建自己的生命周期的原因。
首先我创建了自己的 http-quartz 混合生命周期类:
public class HybridHttpQuartzLifecycle : HttpLifecycleBase<HttpContextLifecycle, QuartzLifecycle>
{
public override string Scope { get { return "HybridHttpQuartzLifecycle"; } }
}
然后我创建了我的 QuartzLifecyle 类:
public class QuartzLifecycle : ILifecycle
{
public void EjectAll()
{
FindCache().DisposeAndClear();
}
public IObjectCache FindCache()
{
return QuartzContext.Cache;
}
public string Scope { get { return "QuartzLifecycle"; } }
}
然后我需要为 Quartz 创建一些上下文类,例如 HttpContext 来保存上下文相关信息。所以我创建了 QuartzContext 类。 当触发一个quartz 作业时,该作业的JobExecutionContext 应该在QuartzContext 中注册。然后将在特定的 JobExecutionContext 下创建 StructureMap 实例的实际缓存 (MainObjectCache)。所以这样在作业执行完成后缓存也会消失,我们就不会有在缓存中处理 UoW 的问题。
此外,由于 _jobExecutionContext 是 ThreadStatic,当我们从 QuartzContext 请求缓存时,它会返回为同一线程保存的 JobExecutionContext 中的缓存。因此,当多个作业同时运行时,它们的 JobExecutionContexts 会单独保存,我们将为每个正在运行的作业有单独的缓存。
public class QuartzContext
{
private static readonly string _cacheKey = "STRUCTUREMAP-INSTANCES";
[ThreadStatic]
private static JobExecutionContext _jobExecutionContext;
protected static void Register(JobExecutionContext jobExecutionContext)
{
_jobExecutionContext = jobExecutionContext;
_jobExecutionContext.Put(_cacheKey, new MainObjectCache());
}
public static IObjectCache Cache
{
get
{
return (IObjectCache)_jobExecutionContext.Get(_cacheKey);
}
}
}
我有一个名为 BaseJobSingleSession 的抽象类,其他作业从该类派生。这个类扩展了 QuartzContext 类。你可以看到我在job被触发的时候注册了JobExecutionContext。
abstract class BaseJobSingleSession : QuartzContext, IStatefulJob
{
public override void Execute(JobExecutionContext context)
{
Register(context);
IUnitOfWork unitOfWork = ObjectFactory.GetInstance<IUnitOfWork>();
try
{
unitOfWork.Begin();
// do stuff ....
unitOfWork.Commit();
}
catch (Exception exception)
{
unitOfWork.RollBack();
}
finally
{
unitOfWork.Dispose();
}
}
}
最后我定义了 UoW 的生命周期:
For<IUnitOfWork>().LifecycleIs(new HybridHttpQuartzLifecycle()).Use<UnitOfWork>();
(对于生命周期和上下文类,我查看了 StructureMap 源代码以获得这个想法。)
请分享您的想法、cmets 和建议:>