Click here to Skip to main content
15,879,095 members
Articles / Programming Languages / C#

NHibernate for Winforms with Spring.Net

Rate me:
Please Sign up or sign in to vote.
4.67/5 (7 votes)
19 Feb 2009CPOL6 min read 95.4K   2.8K   57   22
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:

C#
[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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralThanks Pin
Md. Rashidul Hasan Masum18-Oct-11 20:01
professionalMd. Rashidul Hasan Masum18-Oct-11 20:01 
GeneralMy vote of 5 Pin
Md. Rashidul Hasan Masum18-Oct-11 19:59
professionalMd. Rashidul Hasan Masum18-Oct-11 19:59 
GeneralThe reason why there are no articles about nhibernate and winforms Pin
LAcike@sk6-Nov-09 5:23
LAcike@sk6-Nov-09 5:23 
GeneralPlease Answer Pin
Vikas Misra(TCS)12-Oct-09 5:18
Vikas Misra(TCS)12-Oct-09 5:18 
GeneralRe: Please Answer Pin
Nieve Goor13-Oct-09 9:39
Nieve Goor13-Oct-09 9:39 
GeneralProblem with Northwind Sample Pin
Scott_Blasingame17-Sep-09 10:13
Scott_Blasingame17-Sep-09 10:13 
GeneralRe: Problem with Northwind Sample Pin
Nieve Goor17-Sep-09 10:24
Nieve Goor17-Sep-09 10:24 
GeneralRe: Problem with Northwind Sample Pin
Scott_Blasingame17-Sep-09 11:17
Scott_Blasingame17-Sep-09 11:17 
GeneralRe: Problem with Northwind Sample Pin
Nieve Goor19-Sep-09 9:15
Nieve Goor19-Sep-09 9:15 
GeneralTemplate File Pin
fabianrodrigo200228-May-09 8:44
fabianrodrigo200228-May-09 8:44 
QuestionHow to generate code Pin
William F18-Feb-09 5:36
William F18-Feb-09 5:36 
AnswerRe: How to generate code Pin
Nieve Goor18-Feb-09 6:44
Nieve Goor18-Feb-09 6:44 
GeneralRe: How to generate code Pin
William F18-Feb-09 21:50
William F18-Feb-09 21:50 
GeneralRe: How to generate code Pin
Nieve Goor18-Feb-09 22:34
Nieve Goor18-Feb-09 22:34 
GeneralRe: How to generate code Pin
Nieve Goor19-Feb-09 0:37
Nieve Goor19-Feb-09 0:37 
GeneralRe: How to generate code [modified] Pin
Nieve Goor19-Feb-09 1:58
Nieve Goor19-Feb-09 1:58 
Generalother sources Pin
Daniel M. Camenzind14-Feb-09 1:05
Daniel M. Camenzind14-Feb-09 1:05 
GeneralRe: other sources Pin
Nieve Goor14-Feb-09 5:07
Nieve Goor14-Feb-09 5:07 
Generalstateless session support Pin
guton11-Feb-09 4:01
guton11-Feb-09 4:01 
GeneralRe: stateless session support Pin
Nieve Goor12-Feb-09 2:22
Nieve Goor12-Feb-09 2:22 
GeneralRe: stateless session support Pin
guton12-Feb-09 21:12
guton12-Feb-09 21:12 
GeneralRe: stateless session support Pin
Nieve Goor12-Feb-09 21:32
Nieve Goor12-Feb-09 21:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.