NHibernate Unit Of Work - Multiple Sessions (WinForms)

1.8k views Asked by At

I am struggling with the learning curve for NHibernate.

We are currently porting our C# Winforms application to use NHibernate and are employing the Unit Of Work (UnitOfWork) as detailed by Gabriel Schenker.

NHibernate and the Unit of Work Pattern

We wish to employ the UnitofWork on a "Conversational" basis. For example when the user opens a form we would open a UnitOfWork session and then keep this open until the form is closed. Forms are just an easier way to define a business conversation, we may change this slightly depending upon the implementation but for this example, please use a form opening and closing as the example.

The problem exists when we have the scenario of a form opening on top of another form. In this instance we should have two UnitOfWork operating. One still active for the underlying form and a new UnitOfWork for the new form.

How do we implement this? The UnitOfWork functionality provided by Gabriel only allows one session per UnitOfWork? My initial thoughts are to store sessions in a Dictionary so that sessions can be called from any form or part of the application.

Your thoughts?

3

There are 3 answers

0
James Kovacs On

Read through Ayende's Building a Desktop To-Do Application with NHibernate in MSDN Magazine here: http://msdn.microsoft.com/en-us/magazine/ee819139.aspx. He discusses how to manage multiple units of work within a thick client application.

0
Jamie Ide On

If the 2nd form is a child form -- for example a modal form to edit details -- then it is participating in the same UOW as the parent and the UOW should be passed from the parent to the child, usually in the constructor.

I'm not a fan of the approach in Gabriel Schenker's article; I think it's better to use the ISession directly as a UOW implementation.

Ayende's article referenced in James' answer is good one but we do it a bit differently. For top-level forms that control their own UOW, we have a static method in Program.cs to create an ISession that is invoked in the form's constructor:

private readonly ISession _session;

public frmPlayerViewer()
{
    InitializeComponent();
    // bail out if we're in the designer
    if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
    {
            return;
    }
    _session = Program.OpenEvtSession(FlushMode.Commit);
}

To make sure the ISession is properly disposed, override OnFormClosing:

    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        base.OnFormClosing(e);
        if (!e.Cancel && _session != null)
        {
            if (_session.Transaction.IsActive)
            {
                const string msg = "OnFormClosing with active transaction.";
                log.Error(msg);
                throw new Exception(msg);
            }
            _session.Dispose();
        }
    }

This code is in a base Form that top-level forms extend.

0
CSharpBender On

I've just implemented a Unit of Work for NHibernate named NHUnit which fixes two of the most annoying issues from NHibernate: proxy classes and cartesian product when using fetch. NHUnit decouples your code from the ORM implementation. This means that you can switch to other ORM by just implementing two interfaces: IUnit and IRepository. There is a simple example project on Github to show you how to use NHUnit package.