Click here to Skip to main content
Click here to Skip to main content

NHibernate for Winforms with Spring.Net

By , 19 Feb 2009
 

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

About the Author

Nieve Goor

France France
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralThanksmemberMd. Rashidul Hasan Masum18-Oct-11 20:01 
Thank you very much. For a long time I thought that I will write about spring.net for desktop application. But you have writen very nice. Smile | :)
GeneralMy vote of 5memberMd. Rashidul Hasan Masum18-Oct-11 19:59 
The best article about spring.net (for desktop application ) ever i have read.
GeneralThe reason why there are no articles about nhibernate and winformsmemberLAcike@sk6-Nov-09 5:23 
The main reason is that applications using nhibernate and winforms are not safe. User has to have access to read and write into each table without and interface prohibiting him from certain actions (e.g. directly logging into the database and updating records as he/she wants without a business logic restrictions).
 
Therefore, it is better to use data oriented approach (CRUD procedures in database) or web services in this kind of scenario.
 
Conclusion - the usage of nhibernate and winforms is limited to higly trusted environment (e.g. applications for admins or trusted users).
GeneralPlease AnswermemberMember 159112712-Oct-09 5:18 
Nice article and good effort
 
From past few days i am continuously looking for ORM's/frameworks and came across many like Castle (castleproject.org),Sharp Architecture, Spring etc..I have seen many codes which uses Nhibernate and i have found dll of castle project like Castle.core and spring etc in a project having reference to Nihibernate dll. My questions are
 
1) Does Nhibernate is a combination of all these framework and the other framework dll’s are the part of Nhibernate framework? or we have to follow a certain path to incorporate these frameworks in Nhibernate.
 
2) Each framework or ORM states it's best and could be used as ORM or code modelling tool separately , so can you help me to find the best one?
 
As per the readings done yet i guess SharpArchitecture>Nhibernate>MVC where you can ">" take as "better"
I am also confused with Microsoft Entity framework.
 
Could you suggest me a single framework which has best of all above frameworks(Industry best practices)?
 
3)Does any Nhibernate or Entity framework has the UNIT of work pattern like LLBGenPro.
I know that in Entity Framework they have introduced POCO but is it matured enough?
GeneralRe: Please AnswermemberNieve Goor13-Oct-09 9:39 
Hello there,
First of all, sorry for the late reply.
As for your questions- though they seem to me rather off the scope, I'll try and give you a couple of quick answers at least.
 
1) All the names you've mentioned may work together but are not the same thing.
2) I wouldn't pretend to know who's the best, simply because for each and every project there might be a more suitable solution, and I'm not that experienced nor capable to say what would suite your situation the best. It's very easy to get it wrong and do more harm than good when using these technologies without knowing them good enough.
 
Good luck with all!
GeneralProblem with Northwind SamplememberScott_Blasingame17-Sep-09 10:13 
In the UI layer, I had to add references to Northwind.Data, Northwind.Presentation, Northwind.Services so Spring could see objects or else ContextRegistry.GetContext() would throw a Spring error (Error creating context 'spring.root': Could not load file or assembly 'Northwind.Services' or one of its dependencies.).
 
This is understandable considering that all of the objects for Spring are configured in the app.config. Or did I miss something here and your sample app really doesn't have to do this?
 
If it does, this is concerning because ideally I would want the UI to only know about the Presentation layer and the domain objects.
 
scott
GeneralRe: Problem with Northwind SamplememberNieve Goor17-Sep-09 10:24 
Hey Scott,
 
Yeah, you're more than right in saying that the UI should not know about all the other layers apart from the Presentation and the domain. To be honest, this work was done a couple of years ago when I had little idea how the architecture should look like. To me it was and stayed a good practice in getting to know how things work- I would be very wary of using this template (and for that matter any kind of template) when working on a real project.
 
Still, I may at some point have a second look at it and try to sort it out a bit, just for the sake of it being a bit more educational... Smile | :)
 
cheers,
nieve
GeneralRe: Problem with Northwind SamplememberScott_Blasingame17-Sep-09 11:17 
Thanks for the reply. What approach do you use when building n-Layer apps? I like the idea of using Spring and NHibernate, but they both seem to want to live in every layer of your design and that just rubs me the wrong way.
 
What I have come up with so far is removing the references to the other assemblies and then adding the following lines to the app.config in the spring/context area:
 
<resource uri="assembly://Northwind.Presentation/Northwind.Presentation.config/spring.presentation.config" />
<resource uri="assembly://Northwind.Services/Northwind.Services.config/spring.services.config" />
<resource uri="assembly://Northwind.Data/Northwind.Data.config/spring.data.config" />
 
Then, I moved the object defs to those files. Of course, Spring still needs to know about these assemblies, so I had to do a post-build copy of these assemblies to the bin directory of the UI layer. This may be a bit of a hack, but this is a first pass.
 
scott
GeneralRe: Problem with Northwind SamplememberNieve Goor19-Sep-09 9:15 
Hey Scott,
sorry about the somewhat late reply.
 
The workaround you found was what I came up with at the time, if I remember correctly. Thing is, it stays a workaround...
To be honest, it's been a while since I've used Spring and I don't know what new functionalities the newest versions offer. Currently we're using StructureMap, which was the most suitable choice for the project we're working on, and one of the most appealing aspects of this framework is the possibility to give it the path of your assembly/ies and providing that you follow its default naming conventions (ie UserService implements IUserService, UserRepository implements IUserRepository etc'), StructureMap does all the dirty work- initialising the implementations and injecting them to the ctor, and all that without xmhell or any other config. See example here[^].
But then again, project requirements and contexts differ- do you need to use DDD, an anemic domain, the active record pattern? How big is your domain, how complex are your business rules?
All these and more would (or should) help you in choosing the right architecture and the right tools for you.
As for NH & Spring pushing to live in every layer of your application, I'd argue that when handled correctly, it would be the developers who would push to use them in every layer, if you catch my drift Wink | ;)
 
HTH
nieve
GeneralTemplate Filememberfabianrodrigo200228-May-09 8:44 
One best practice would be this one:
 
Read the templates from files and replace the dynamic parts with the dynamic content using custom tags, for example: {entityname}, etc. Not hardcode all the source code in writeline sentences.
 
Very good work
 
Thanks Smile | :)
 
Im a programmer

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130617.1 | Last Updated 19 Feb 2009
Article Copyright 2009 by Nieve Goor
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid