Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

NHibernate for Winforms with Spring.Net

0.00/5 (No votes)
19 Feb 2009 3  
A Winforms Nhibernate framework code generation

Introduction

When I first researched the usage of NHibernate in a Winforms environment, I was rather disappointed to find out there's very few (to none) articles that discuss the subject in a general sense or introduce it to beginners (like me). This is why I've decided to summarise most of my findings into one article, providing a sort of a framework with which developers, who are new to NHibernate and are about to work with it in a Winforms environment, could find a starting point.

While this article does not pretend in any way to provide a set of best practices, I would be very happy to get any constructive feedback that may contribute and create eventually a sort of a Winforms parallel to Billy McCafferty's NHibernate Best Practices For ASP.NET.

Background

Before reading this article, I would suggest anyone who may not be familiar with the term "Dependency Injection" (DI) to read either McCafferty's article on DI, or Oren Eini's brilliant take on the subject.

You will also need the Spring.Net framework (although any other container would do. I chose to work with spring for this example) and the SmartCode code generation tool.

Using the Code

Now, when beginning to work with NHibernate in Winforms, you'd probably see first of all that the main difference between Winforms and a web environment is the way you deal with your sessions. While working with the web, the sessions are opened and closed per Requests normally. This however proves to be more complicated in Winforms, since you don't have requests, and leaving a session open per window might end in an extremely heavy session cache, simply because a window might stay open and 'alive' for a much longer period than an ASP.NET request. In multiuser applications, this might also increase the possibility of getting StaleObjectStateException.

The solution that seems to be the most appropriate is fairly documented in the Spring forums. However, this may lead to another problem of lazy loading mode, as a session will not be open whenever you would like to lazy load a collection. To this problem, unfortunately, there is no one straight answer, simply because each case should be considered apart. More on that could be found also on the spring forum, or in another article of mine, Lazy Initializer for NHibernate.

Session management would therefore become less chaotic when working with spring's transaction attributes and TransactionManager. All you need to do is simply add the attribute on the service method that'll call the data access layer (DAL) like so:

[Transaction(ReadOnly=false)]
public virtual void AccessMyDB()
{
    // Do something with the db...
}

When working in the DAL with Springs' HibernateTemplate, this will allow spring to create a new session or fetch an already existing open session whenever needed (also, when catching an exception, the transaction will rollback by default. The transactions can also be globally parameterised in the spring XML configuration section).

Working with the HibernateTemplate becomes even more easy with the HibernateDaoSupport parent class the folks in spring created for us. What I've done was simply created a base dao all my daos inherit, while the base dao inherits from the HibernateDaoSupport. You may find more information on the HibernateDaoSupport in the spring documentation.

This approach (allocating a transaction / session per service method) will reduce the probability of handling a StaleObjectStateException in multiuser applications. When working on applications where it's unlikely two users will modify the same entity/ies at the same time, you could use a different approach where the life of a session can span a number of service methods (some more on that could be found on Gustavo Ringles blog- and thanks to Daniel M. Camenzind for sharing).

As for the 'higher' layers- the user interface and the model-view layer, I found the MVP pattern to be the most elegant and suitable solution for a better separation between the service and the user interface layers. With the MVP pattern, no service code will be found directly in the user interface, but in the 'presentation' layer. This will then allow the insertion of a whole new user interface layer (if for example, you'd like one day to move from Winforms to XAML).
More on the Model-View-Presenter pattern could be found in Mike Peretz article on MVP using DI.

Generating the Framework

Now, to facilitate the creation of such a framework, I have re-written and extended the base template found in the SmartCode code generation tool. Why SmartCode of all the codegen tools out there that do a good job with NHibernate? Well, in my opinion SmartCode does the job pretty well, delivers a code that is fairly minimal (which was the best solution for my case) and highly modifiable. Also, the templates are all written in C# which was a plus for me. If you'd like to change the templates to suit you better, you'd see that it won't take too long to get the hang of it. Here is a good article on how to work with SmartCode (by its creator); you could start reading it from the 'SmartCode Projects' section.
You may download the templates from the link on the top of the page.

All you'll need to do now is simply create a new solution and add the following projects to it:

  • MySolution.Core
  • MySolution.Data
  • MySolution.Services
  • MySolution.Presentation
  • and your UI (MySolution.UI if you'd like...)

You should then add a reference to your Core project in all of the other projects. A reference to NHibernate should be added as well to the Core and Data projects. The Data Project should have references to the Spring.Aop, Spring.Core, Spring.Data, Spring.Data.NHibernate, Spring.Data.NHibernate12 and Spring.Services DLLs. The Service project should reference the Spring.Core, Spring.Data and Spring.Data.NHibernate12 DLLs.

After generating the code, simply drag and drop the code generated in the folder you've selected: all the subfolders of the Core folder to your Core project, Data subfolder to Data project etc. The contents of the app.config.xml file should be copied into your app.config file. This will contain your spring configurations.

An example of the code I've generated for the Northwind database could be found here (a zip of 7.1 MB, since it's the whole solution, which is also why I didn't attach it to the article directly). The only thing I've added was the Form1 implementation of the IEmployeeView, the LoadEmployeeById event to the IEmployeeView, and the LoadEmployeeById event handler in the EmployeeController.
If you feel something is missing in the template, let me know and I'll do my best to add it.

Conclusion

The patterns I've chosen to work with are by no means the best practices to working with NHibernate in Winforms. This article serves only to condense all that I've learned and the material I found on the subject. Even my experience with working with these tools is unfortunately limited. What I did was simply summarise other people's experiences to one place. If you'd like to add anything or you've written a similar article on the subject, feel free to let me know.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here