如何在多线程控制台应用程序中设置具有 Sharp 架构的 NHibernate?

发布于 2024-12-01 06:55:46 字数 1624 浏览 0 评论 0原文

我对这些技术还很陌生。这里真正的问题是如何管理控制台应用程序中每个线程的会话。目前,如果我将其作为单线程运行,那么一切都很好。一旦切换到多线程模型,我就会开始看到会话级别的争用(因为 Session 对象在设计上不是 adsafe)、KeyNotFound 异常(以及其他异常)开始被抛出。

在 Web 应用程序中,您可以执行以下操作:

    /// <summary>
    /// Due to issues on IIS7, the NHibernate initialization cannot reside in Init() but
    /// must only be called once.  Consequently, we invoke a thread-safe singleton class to
    /// ensure it's only initialized once.
    /// </summary>
    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        NHibernateInitializer.Instance().InitializeNHibernateOnce(
            () => InitializeNHibernateSession());
    }

    /// <summary>
    /// If you need to communicate to multiple databases, you'd add a line to this method to
    /// initialize the other database as well.
    /// </summary>
    private void InitializeNHibernateSession()
    {            

        var path = ConfigurationManager.AppSettings["NHibernateConfig"];
        NHibernateSession.Init(
            webSessionStorage,
            new string[] { Server.MapPath("~/bin/foo.Data.dll") },
            new AutoPersistenceModelGenerator().Generate(),
            Server.MapPath("~/App_Configuration/" + path ));
    }

// sample of my console app... very simple
static void Main(string[] args)
{
  InitializeNHibernateSession();
  while(true)
  {
    Task.Factory.StartNew(() => SomeAwesomeLongRunningPieceOfWork());
  }
}

这实际上在 global.asax 中为每个线程(Web 请求)执行一次初始化。

关于如何在控制台应用程序中设置此功能(会话管理)有什么想法吗?

I'm still pretty new to these technologies. The real problem here is how to manage the sessions per thread in the console app. Currently, if I run it as a single thread then all is well. As soon as I switch to a multi-threaded model, I'll start to see contention at the session level (because the Session object is not theadsafe by design) KeyNotFound exceptions (among others) start to get thrown.

In a web app, you'd do something like this:

    /// <summary>
    /// Due to issues on IIS7, the NHibernate initialization cannot reside in Init() but
    /// must only be called once.  Consequently, we invoke a thread-safe singleton class to
    /// ensure it's only initialized once.
    /// </summary>
    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        NHibernateInitializer.Instance().InitializeNHibernateOnce(
            () => InitializeNHibernateSession());
    }

    /// <summary>
    /// If you need to communicate to multiple databases, you'd add a line to this method to
    /// initialize the other database as well.
    /// </summary>
    private void InitializeNHibernateSession()
    {            

        var path = ConfigurationManager.AppSettings["NHibernateConfig"];
        NHibernateSession.Init(
            webSessionStorage,
            new string[] { Server.MapPath("~/bin/foo.Data.dll") },
            new AutoPersistenceModelGenerator().Generate(),
            Server.MapPath("~/App_Configuration/" + path ));
    }

// sample of my console app... very simple
static void Main(string[] args)
{
  InitializeNHibernateSession();
  while(true)
  {
    Task.Factory.StartNew(() => SomeAwesomeLongRunningPieceOfWork());
  }
}

Which essentially executes the initialization once per thread (web request) in the global.asax.

Any ideas on how to set this (the session management) up in a console app?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

醉生梦死 2024-12-08 06:55:46

这对我有用:

// Three threads:
for (int i = 0; i < 3; i++)
{
   Thread curThread = new Thread(StartThread);
   curThread.Start();
}

private void StartThread()
{
      NHibernateInitializer.Instance().InitializeNHibernateOnce(InitializeNHibernateSession);
      SomeAwesomeLongRunningPieceOfWork();            
}

private void InitializeNHibernateSession()
{
   var path = ConfigurationManager.AppSettings["NHibernateConfig"];

   NHibernateSession.Init(
      new ThreadSessionStorage(),
      new string[] { "foo.Data.dll" },
      new AutoPersistenceModelGenerator().Generate(),
      "./App_Configuration/" + path);
}

关键是这个类,我从以下位置获得:

http://groups.google.com/group/sharp-architecture/browse_thread/thread/ce3d9c34bc2da629?fwc=1
http://groups.google.com/group/sharp-architecture/browse_thread/thread/51794671c91bc5e9/386efc30d4c0bf16#386efc30d4c0bf16

public class ThreadSessionStorage : ISessionStorage
{
    [ThreadStatic]
    private static ISession _session;
    public ISession Session
    {
        get
        {
            return _session;
        }
        set
        {
            _session = value;
        }
    }

    public ISession GetSessionForKey(string factoryKey)
    {
        return Session;
    }

    public void SetSessionForKey(string factoryKey, ISession session)
    {
        Session = session;
    }

    public IEnumerable<ISession> GetAllSessions()
    {
        return new List<ISession>() { Session };
    }
}

它工作得很好。

This worked for me:

// Three threads:
for (int i = 0; i < 3; i++)
{
   Thread curThread = new Thread(StartThread);
   curThread.Start();
}

private void StartThread()
{
      NHibernateInitializer.Instance().InitializeNHibernateOnce(InitializeNHibernateSession);
      SomeAwesomeLongRunningPieceOfWork();            
}

private void InitializeNHibernateSession()
{
   var path = ConfigurationManager.AppSettings["NHibernateConfig"];

   NHibernateSession.Init(
      new ThreadSessionStorage(),
      new string[] { "foo.Data.dll" },
      new AutoPersistenceModelGenerator().Generate(),
      "./App_Configuration/" + path);
}

The key was this class, which I got from:

http://groups.google.com/group/sharp-architecture/browse_thread/thread/ce3d9c34bc2da629?fwc=1
http://groups.google.com/group/sharp-architecture/browse_thread/thread/51794671c91bc5e9/386efc30d4c0bf16#386efc30d4c0bf16

public class ThreadSessionStorage : ISessionStorage
{
    [ThreadStatic]
    private static ISession _session;
    public ISession Session
    {
        get
        {
            return _session;
        }
        set
        {
            _session = value;
        }
    }

    public ISession GetSessionForKey(string factoryKey)
    {
        return Session;
    }

    public void SetSessionForKey(string factoryKey, ISession session)
    {
        Session = session;
    }

    public IEnumerable<ISession> GetAllSessions()
    {
        return new List<ISession>() { Session };
    }
}

And it works just fine.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文