Sebastian Edelmeier
Sebastian Edelmeier

Reputation: 4157

How to manage a Session as a unit-of-work in NHibernate?

After a few years using NHibernate in Winforms and WPF, I still seem to have missed one very important point, which became too obvious when I ran this code snippet:

 ISessionFactory sf = Fluently.Configure()
                              .Database(MsSqlConfiguration.MsSql2008
                                .ConnectionString(c => c.Is(connectionString)))
                              .Mappings(x => x.FluentMappings
                                .AddFromAssemblyOf<MyClass>())
                              .BuildSessionFactory();

 for (int i = 0; i < 100; i++)
 {
     new Task(()=>
     {
         Console.WriteLine("{0}, {1}",
           i, 
           sf.OpenSession().QueryOver<MyClass>().List().Count);
     }).Start();
 }

This causes a lot of load, I surmise.

Honestly, the only thing I remember having read about Session handling is: Implement Unit Of Work, which proclaims atomar sessions. So, taking a look at the pattern, I have a few concerns/questions.

EDIT: Oren Eini has stated the very same thing as being a problem in an early article of his. There, he says MicroManaging (=> use and immediate Dispose) cuts off NH functionality like LazyLoading and ChangeTracking. It seems to me though, that UnitOfWork is a Session MicroManagement pattern. So, what's the cleanest solution? Tracking changes myself and using MicroManagement? Monolithic sessions (= Memleak by design)? What if, unlike the example by Oren, you don't have many subdialogs that can restrict session lifetime?

Upvotes: 4

Views: 1370

Answers (1)

jbl
jbl

Reputation: 15413

How does lazy loading fit in the picture?

Lazy loading fits in the picture of one session. Once an object has been loaded, lazy loading allows traversing the object's graph without needing to know if an object property has already been loaded from the db, and without eagerly loading all the object graph.

Seems perfect, but there are issues though, like "n+1 select"

If I load my Data using one session, and then close it, lazy loading won't work.

Another session, loading the same object from db, will not benefit from the properties lazy loaded in the previous session.

So, basically, the unit of work can not close / dispose the Session, meaning it is infinitely large.

I am not sure I understand this. I guess Session is the Unit of Work.

Sessions have features like IsDirty. If loading and saving objects is done by separate sessions, how can this still be utilized?

Loading and saving should not be done in separate sessions. I guess it is the point of the IsDirty property.

This might give you many hints on NH handling : https://softwareengineering.stackexchange.com/q/100534

Hope this will help

Edit : about your second question. A usual web scenario would be like :

  1. open a NH session
  2. load a NH entity
  3. transfer the NH entity properties in a POCO for display in the UI (keep track of Id, of course)
  4. close the NH session
  5. later on (user has made some changes and hits "Save" Button), open the NH session
  6. load the corresponding NH entity (by its Id)
  7. update the NH entity according to the new POCO fields
  8. persist changes in the DB
  9. close the NH Session

1,2 and 4 are parts of a first unit of work. 5,6,7,8 and 9 are parts of a second unit of work.

Upvotes: 4

Related Questions