gpt4 book ai didi

.net - StructureMap 从线程本地范围返回一个已处理的 nHibenrate session 对象

转载 作者:行者123 更新时间:2023-12-04 12:25:16 24 4
gpt4 key购买 nike

[或] 如何为 http 请求和 quartz 作业使用的 UoW 定义 StructureMap 生命周期

我有这个使用 SM 进行 IoC 的 Web 应用程序。我正在使用 HybridHttpOrThreadLocalScoped 范围来存储我的 nHibernate ISession 对象。对于我的 Web 请求,这在每个请求的 session 中都可以正常工作。

但我也有quartz.net 来安排几个工作。该作业使用相同的工作单元来获取 ISession 对象。在这种情况下,当调度程序启 Action 业时,一开始一切正常,作业运行良好几次,直到作业线程 id 重复为止。

想象一下,当作业被调度时,它开始在 ID 为 11、12、13 的线程中运行,然后再次以线程 ID 11 运行。此时,结构映射返回一个已经被处理的 session 对象,我得到“System.ObjectDisposedException: Session is closed!”错误。

因此,从我所见, session 保存在线程本地存储中,在我的工作单元结束时处理 session 后, session 对象仍保存在线程本地存储中。 似乎在线程终止后,它的本地存储并未清除,并且以某种方式创建具有相同 id 的新线程时,structuremap 在旧线程本地存储中查找 session (应该为我相信的新线程清除)并返回已经处理的 session 对象。

问题:

  • 有没有办法清除线程本地存储(终止时)?
  • 对于线程范围的对象,是否有等效的“ReleaseAndDisposeAllHttpScopedObjects”?
  • 有没有办法使(或弹出)已处置的对象无效,因此即使 SM 查找它,它也找不到任何对象并且必须创建一个新实例?

  • 我希望我说清楚了我的问题。这花了我几个小时的时间,但我仍然没有找到解决方法。我很感激任何提示:>

    更新:
    我添加了自己的解决方案,使 StructureMap 提供的 UoW 可以同时处理 http 请求和 quartz 作业。如果您有更好/更简单/更简单的解决方案,请告诉我。

    最佳答案

    我正在重新审视我为使 StructureMap 与 UoW per Http 和 UoW perquartz 工作一起工作所做的工作,我决定在这里分享我的解决方案。

    所以我的想法是,当有 http 上下文时,我想使用 StructureMap Hybrid 范围来获取 UoW 的实例,并在没有 http 上下文时(例如,当 quartz 作业触发时)为每个线程获取不同的 UoW 实例。像这样:

    For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<UnitOfWork>();

    http 的 UoW 工作正常。问题是每个线程的 UoW。

    这是发生的事情。当 Quratz 作业触发时,它会从线程池中拉出一个线程并开始使用该线程执行作业。当工作开始时,我请求 UoW。 StructureMap 在该线程的本地存储下查找以返回 UoW,但由于找不到任何它实例化一个并将其保存在线程的本地存储下。我得到了 UoW,然后执行开始、提交、处理,一切都很好。

    当从之前用于触发作业(并使用 UoW)的线程池中提取线程时,会发生问题。在这里,当您请求一个 UoW 时,StructureMap 在缓存(线程本地存储)中查找并找到一个 UoW 并将其返回给您。但是问题是UoW被处理了!

    所以我们不能真正为 quartz 作业使用每个线程的 UoW,因为线程本身没有被释放,它们持有旧的缓存已释放的 UoW。 线程的生命周期基本上与 quartz 作业的生命周期不匹配。 这就是为什么我为 quartz 工作创建了自己的生命周期。

    首先,我创建了自己的 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 类。您可以看到我在作业被触发时注册了 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 源代码以获得想法。)

    请分享您的想法、意见和建议:>

    关于.net - StructureMap 从线程本地范围返回一个已处理的 nHibenrate session 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3169989/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com