NHibernate thread safety with session

后端 未结 3 2089
有刺的猬
有刺的猬 2021-01-31 12:30

I\'ve been using NHibernate for a while now and have found from time to time that if I try to request two pages simultaniously (or as close as I can) it will occasionally error.

3条回答
  •  旧时难觅i
    2021-01-31 12:46

    While I haven't seen your entire codebase or the the problem you're trying to solve, a rethinking of how you are using NHibernate might be in order. From the documentation:

    You should observe the following practices when creating NHibernate Sessions:

    • Never create more than one concurrent ISession or ITransaction instance per database connection.

    • Be extremely careful when creating more than one ISession per database per transaction. The ISession itself keeps track of updates made to loaded objects, so a different ISession might see stale data.

    • The ISession is not threadsafe! Never access the same ISession in two concurrent threads. An ISession is usually only a single unit-of-work!

    That last bit is the most relevant (and important in the case of a multithreaded environment) to what I'm saying. An ISession should be used once for a small atomic operation and then disposed. Also from the documentation:

    An ISessionFactory is an expensive-to-create, threadsafe object intended to be shared by all application threads. An ISession is an inexpensive, non-threadsafe object that should be used once, for a single business process, and then discarded.

    Combining those two ideas, instead of storing the ISession itself, store the session factory since that is the "big" object. You can then employ something like SessionManager.GetSession() as a wrapper to retrieve the factory from the session store and instantiate a session and use it for one operation.

    The problem is also less obvious in the context of an ASP.NET application. You're statically scoping the ISession object which means it's shared across the AppDomain. If two different Page requests are created within that AppDomain's lifetime and are executed simultaneously, you now have two Pages (different threads) touching the same ISession which is not safe.

    Basically, instead of trying to keep a session around for as long as possible, try to get rid of them as soon as possible and see if you have better results.

    EDIT:

    Ok, I can see where you're trying to go with this. It sounds like you're trying to implement the Open Session In View pattern, and there a couple different routes you can take on that:

    If adding another framework is not an issue, look into something like Spring.NET. It's modular so you don't have to use the whole thing, you could just use the NHibernate helper module. It supports the open session in view pattern. Documentation here (heading 21.2.10. "Web Session Management").

    If you'd rather roll your own, check out this codeproject posting by Bill McCafferty: "NHibernate Best Practices". Towards the end he describes implementing the pattern through a custom IHttpModule. I've also seen posts around the Internet for implementing the pattern without an IHttpModule, but that might be what you've been trying.

    My usual pattern (and maybe you've already skipped ahead here) is use a framework first. It removes lots of headaches. If it's too slow or doesn't fit my needs then I try to tweak the configuration or customize it. Only after that do I try to roll my own, but YMMV. :)

提交回复
热议问题