Hi,
I dont know why two sessions are open..
I am unsure which pattern to use for data retrieval with NHibernate - I'm using something I adapted from an open-source project..
I am not expecting you to read all of my code (may take too much time), so if you know of a good pattern to use for an NHibernate helper, then Id be happy to do the tinkering to make it work with my code and get back to you if I still have the same problem.
Thank you so much for your help,
Christian
Here's the code, in case you feel inclined:
Code:
<<<< Databroker Class >>>>
public class DataBroker
{
...
public NHibernateHelper dataHelper;
...
public int SaveHotelLocation(HotelLocation hotelLocation)
{
ITransaction tx = dataHelper.ActiveSession.BeginTransaction();
try
{
hotelLocation.ID = (int) dataHelper.ActiveSession.Save(hotelLocation);
tx.Commit();
}
catch (Exception ex)
{
if(tx!=null) tx.Rollback();
throw new Exception("Unable to save hotelLocation", ex);
}
finally{ dataHelper.ActiveSession.Close(); }
return hotelLocation.ID;
}
...
}
Code:
<<<< NHibernateHelper class >>>>
using System;
using System.Configuration;
using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
using log4net;
using NHibernate;
using NHibernate.Expression;
namespace NHibernateHelper
{
public class NHibernateHelper
{
private static readonly ILog log = LogManager.GetLogger(typeof(NHibernateHelper));
private ISessionFactory _factory;
private ISession _activeSession;
private static IDictionary getConfigurationSection(string configSectionName)
{
object config = ConfigurationSettings.GetConfig(configSectionName);
Hashtable dictionary = new Hashtable();
if( config == null )
{
return null;
}
NameValueCollection properties = config as NameValueCollection;
if( properties == null )
{
return null;
}
foreach( string key in properties )
{
dictionary[ key ] = properties[ key ];
}
return dictionary;
}
/// <summary>
/// Get the active NHibernate session.
/// </summary>
public ISession ActiveSession
{
get { return this._activeSession; }
}
public NHibernateHelper(string configSectionName, Assembly assembly) : this( NHibernateHelper.getConfigurationSection(configSectionName), assembly )
{
}
public NHibernateHelper(string configSectionName, Assembly assembly, bool openSession) : this( NHibernateHelper.getConfigurationSection(configSectionName), assembly, openSession)
{
}
/// <summary>
/// Create a repository for core objects.
/// </summary>
public NHibernateHelper(System.Collections.IDictionary properties, Assembly assembly) : this(properties, assembly, false)
{
}
/// <summary>
/// Create a repository for core objects.
/// </summary>
/// <param name="openSession">Indicate if the CoreRepository should open a session and keep it in memory.</param>
public NHibernateHelper(System.Collections.IDictionary properties, Assembly assembly, bool openSession)
{
this._factory = SessionFactory.GetInstance(properties, assembly).GetNHibernateFactory();
if (openSession)
{
this._activeSession = this._factory.OpenSession();
}
}
/// <summary>
/// Open a NHibernate session.
/// </summary>
public void OpenSession()
{
if (this._activeSession == null || ! this._activeSession.IsOpen)
{
this._activeSession = this._factory.OpenSession();
}
else
{
throw new InvalidOperationException("The repository already has an open session");
}
}
/// <summary>
/// Flushes the current active NHibernate session.
/// </summary>
public void FlushSession()
{
if (this._activeSession != null && this._activeSession.IsOpen)
{
this._activeSession.Flush();
}
}
/// <summary>
/// Close the active NHibernate session
/// </summary>
public void CloseSession()
{
if (this._activeSession != null)
{
if (this._activeSession.IsOpen)
{
this._activeSession.Close();
}
this._activeSession.Dispose();
}
}
#region Generic methods
/// <summary>
/// Generic method for retrieving single objects by primary key.
/// </summary>
/// <param name="type"></param>
/// <param name="id"></param>
/// <returns></returns>
public object GetObjectById(Type type, int id)
{
if (this._activeSession != null)
{
return this._activeSession.Load(type, id);
}
else
{
throw new NullReferenceException("The repository doesn't have an active session");
}
}
/// <summary>
/// Get all objects of a given type.
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public IList GetAll(Type type)
{
return GetAll(type, null);
}
/// <summary>
/// Get all objects of a given type and add one or more names of properties to sort on.
/// </summary>
/// <param name="type"></param>
/// <param name="sortProperties"></param>
/// <remarks>Sorting is Ascending order. Construct a specific query/method when the sort order
/// should be different.</remarks>
/// <returns></returns>
public IList GetAll(Type type, params string[] sortProperties)
{
ICriteria crit = this._activeSession.CreateCriteria(type);
if (sortProperties != null)
{
foreach (string sortProperty in sortProperties)
{
crit.AddOrder(Order.Asc(sortProperty));
}
}
return crit.List();
}
/// <summary>
/// Generic method to insert an object.
/// </summary>
/// <param name="obj"></param>
public void SaveObject(object obj)
{
ITransaction trn = this._activeSession.BeginTransaction();
try
{
// Try to find a UpdateTimestamp property and when found, set it to the current date/time.
PropertyInfo pi = obj.GetType().GetProperty("UpdateTimestamp");
if (pi != null)
{
pi.SetValue(obj, DateTime.Now, null);
}
this._activeSession.Save(obj);
trn.Commit();
}
catch (Exception ex)
{
trn.Rollback();
throw ex;
}
}
/// <summary>
/// Generic method to update an object.
/// </summary>
/// <param name="obj"></param>
public void UpdateObject(object obj)
{
ITransaction trn = this._activeSession.BeginTransaction();
try
{
this._activeSession.Update(obj);
trn.Commit();
}
catch (Exception ex)
{
trn.Rollback();
throw ex;
}
}
/// <summary>
/// Delete a specific object. Settings in the mapping file determine if this cascades
/// to related objects.
/// </summary>
/// <param name="obj"></param>
public void DeleteObject(object obj)
{
ITransaction trn = this._activeSession.BeginTransaction();
try
{
this._activeSession.Delete(obj);
trn.Commit();
}
catch (Exception ex)
{
trn.Rollback();
throw ex;
}
}
/// <summary>
/// Mark an object for deletion. Commit the deletion with Session.Flush.
/// </summary>
/// <param name="obj"></param>
public void MarkForDeletion(object obj)
{
this._activeSession.Delete(obj);
}
#endregion
}
}
Code:
<<<< SessionFactory class >>>>
using System;
using System.Reflection;
using NHibernate;
using NHibernate.Cfg;
namespace NHibernateHelper
{
/// <summary>
/// The SessionFactory provides the NHibernate sessions and provides the possibility to register
/// additional classes with NHibernate by modules.
/// </summary>
public class SessionFactory
{
private static SessionFactory __sessionFactory = null;
private static SessionFactory _sessionFactory(System.Collections.IDictionary properties, Assembly assembly)
{
if(SessionFactory.__sessionFactory == null) SessionFactory.__sessionFactory = new SessionFactory(properties, assembly);
return SessionFactory.__sessionFactory;
}
private Configuration _nhibernateConfiguration;
private ISessionFactory _nhibernateFactory;
private bool _classesAdded = false;
/// <summary>
/// Default constructor.
/// </summary>
protected SessionFactory(System.Collections.IDictionary properties, Assembly assembly)
{
RegisterClasses( properties, assembly );
}
/// <summary>
/// Gets the one instance of the SessionFactory. This is done with a singleton so we don't have
/// to register mappings etc. with every request.
/// </summary>
/// <returns></returns>
public static SessionFactory GetInstance(System.Collections.IDictionary properties, Assembly assembly)
{
return _sessionFactory( properties, assembly );
}
/// <summary>
/// GetNHibernateFactory returns the current NHibernate ISessionFactory.
/// </summary>
public ISessionFactory GetNHibernateFactory()
{
return this._nhibernateFactory;
}
/// <summary>
/// Get a new NHibernate session.
/// </summary>
/// <returns></returns>
public ISession GetSession()
{
return this._nhibernateFactory.OpenSession();
}
/// <summary>
/// Add a class to the NHibernate mappings.
/// If the class already is mapped, nothing will happen.
/// </summary>
/// <param name="type"></param>
public void RegisterPersistentClass(Type type)
{
if (this._nhibernateConfiguration.GetClassMapping(type) == null)
{
// Class isn't mapped yet, so do it now.
this._nhibernateConfiguration.AddClass(type);
this._classesAdded = true;
}
}
/// <summary>
/// Rebuild the NHibernate ISessionFactory. Use it after registering new classes.
/// </summary>
public bool Rebuild()
{
// Rebuild NHibernate SessionFactory to activate the new mapping.
if (this._classesAdded)
{
this._nhibernateFactory = this._nhibernateConfiguration.BuildSessionFactory();
this._classesAdded = false;
return true;
}
else
{
return false;
}
}
private void RegisterClasses(System.Collections.IDictionary properties, Assembly assembly )
{
Configuration config = new Configuration();
config.AddProperties(properties);
this._nhibernateConfiguration = config.AddAssembly( assembly );
this._nhibernateFactory = this._nhibernateConfiguration.BuildSessionFactory();
}
}
}