I as I mentioned in my last post, the standard out of the box setup for NHibernate in Asp.Net does not work well with Ajax calls. The standard approach you will see in the online docs and examples puts the Session.Close() method in the OnEndRequest event handler. This will work when you're doing PostBacks and probably partial post-backs, but I avoid those (blog entry on why later). But on a Ajax method call, OnEndRequest will not do it for you since it's not called after your webservice call.
Now I'm sure there is another http module that you might be able to tap into. I've seen some diagrams of the asp.net ajax event model, but not studied it seriously. My approach was to check that the session was open before my save method call and close afterwards in my Nhibernate Implementation of my repositories. In order to reduce repetive code and ensure that I always closed my connection, I used the Template Method Pattern. There are lots of examples of Template Method on the web, here is the dofactory link to their example: http://www.dofactory.com/Patterns/PatternTemplate.aspx.
The purpose of the Template Method is to break up an algorithm into smaller steps and let subclasses perform parts of the algorithm. This allows you change the behavior of the method, but keep a consistent api in your system.
Here is the UML Diagram from dofactory.
Though I'm not sure how helpful the diagram is. Here is the specific implementation in how I used it. This is after some refactoring. I actually started with ISprintRepository and then factored out the Repository<T>. When creating new repositories, this will ensure some common features and it hides the generic interface to make typing a little easier when instantiating these things
public interface ISprintRepository : Repository<Sprint>
I then create a NhibernateBaseRepository class that has the following abstract proctected and public methods.
protected abstract ValidationResult<T> SaveInternal(T item);
public ValidationResult<T> Save(T item)
{
try
{
CheckConnectionStatus();
ValidationResult<T> result = SaveInternal(item);
return result;
}
finally
{
NHibernateSession.Flush();
NHibernateSession.Close();
}
}
This is the basic structure of the template method. Declare your public method in the base class and create abstract or virtual methods to allow your sub classes to fill in the blanks. Now you implement your concrete class and do the real work in the SaveInternal method.
protect ed override ValidationResult<Sprint> SaveInternal(Sprint item)
{
ValidationResult<Sprint> result = new ValidationResult<Sprint>();
try
{
true;
}
catch (System.Exception e)
{
result.Result = false;
result.Messages.Add(e.ToString()); return result;
}
ISprintRepository sr = new SprintRepository();
vr = sr.Save(spr);
}
result.Item = item;
That's it in a nutshell. Now all that is left it so actually use the implementation in your application somewhere.
This solves the problem for handling things that have at same method signature like save, update and delete. But this wouldn't be as pretty for specific query methods like GetByFK(xxx). I haven't worked this out yet, but I think that I am going to use a delegate approach for this. I'll let you know as soon as I get something down on paper that I like. All of this is coming from one of my pet projects I work on in my spare time, so it's not exactly getting done in record time. But I am making progress.