Correct use of the NHibernate Unit Of Work pattern and Ninject

前端 未结 3 788
余生分开走
余生分开走 2020-12-07 22:17

I have the following implementation and would like some feedback as to whether it makes correct use of NHibernate for sessions and transactions.

public inter         


        
相关标签:
3条回答
  • 2020-12-07 22:34

    I have a mostly CRUD type of application, and I implemented the Unit Of Work with Repository pattern, but couldn't really get away from the Session/Transaction split. Sessions and Transactions need different lifetimes. In the desktop world, a Session is usually "per-screen" and a Transaction is "per-user-action".

    More information in this excellent article.

    So what I ended up with was:

    • IUnitOfWork -> Wraps session, implements IDisposable
    • IAtomicUnitOfWork -> Wraps transaction, implements IDisposable
    • IRepository -> Provides Get, Save, Delete and query access

    I made it so that you need an IUnitOfWork to build an IAtomicUnitOfWork and you need an IAtomicUnitOfWork to build an IRepository, so that enforces proper transaction management. That's really all I gained by implementing my own interfaces.

    As jeroenh said, you are almost just as well to use ISession and ITransaction but in the end I felt a little better writing all my code against an interface that I defined.

    0 讨论(0)
  • 2020-12-07 22:41

    First observation: your repository should not commit the unit of work. This defeats the whole point of the unit of work pattern. By immediately saving your changes inside the repository, you're "micro managing" the NHibernate Session.

    The unit of work should be referenced higher up the stack, in your application/service layer. This allows you to have application code that performs several actions, potentially on different repositories, and still at the end commit everything at once.

    The UnitOfWork class itself looks Ok, though you should ask yourself if you really need it. In NHibernate, the ISession IS your unit of work. Your UnitOfWork class does not seem to add a lot of value (especially since you're exposing the CurrentSession property anyway)

    But you do need to think about it's lifetime. I think you have it wrong on this point. Session lifetime management depends on the type of application you're developing: in a web app, you typically want to have a unit of work per request (you might want to google on 'nhibernate session per request'). In a desktop app it's slightly more complicated, you will most of the time want a 'session per screen' or 'conversation per business transaction'.

    0 讨论(0)
  • 2020-12-07 22:47

    An important part of the answer lies in what you want your transaction sizes to be. Right now (as jeroenh has indicated) the transaction is per method invocation on your repository. This is very small and probably not needed. I created an ASP.MVC application and it uses a transaction size that included everything from a single http request. This could be multiple database reads/updates. I am using the same unit of work and Ninject for IOC. Take a look, maybe something will help with your issues:

    http://bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/

    http://bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/

    http://bobcravens.com/2010/09/the-repository-pattern-part-2/

    http://bobcravens.com/2010/11/using-ninject-to-manage-critical-resources/

    Hope this helps.

    Bob

    0 讨论(0)
提交回复
热议问题