Hi!
You could do something like this:
Code:
/// <summary>
/// The SessionScopeGuard will guard the session and close
/// it when the guard is disposed.
/// </summary>
public class SessionScopeGuard : IDisposable
{
private static readonly ILog log = LogManager.GetLogger(typeof(SessionScopeGuard));
private SessionScope scope;
private bool transactional;
private ISessionFactory sessionFactory;
/// <summary>
/// Read-only scope.
/// </summary>
public SessionScopeGuard(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory
transactional = false;
scope = new SessionScope(sessionFactory, false);
scope.Open();
}
/// <summary>
/// Transactional scope.
/// </summary>
public SessionScopeGuard(ISessionFactory sessionFactory, bool transactional)
{
this.sessionFactory = sessionFactory
this.transactional = transactional;
scope = new SessionScope(sessionFactory, false);
scope.Open();
// So far, we have a read only session, that means the FlushMode is Never.
// If we expect one or more transactions to take place while this session is open,
// then we must change the FlushMode to Auto. This is what the transactional block
// below does:
if (transactional)
{
ISession session = SessionFactoryUtils.GetSession(sf, false);
// Modifying default FlushMode from ReadOnly to Auto:
session.FlushMode = FlushMode.Auto;
}
}
/// <summary>
/// Exposes the session created by the guard...
/// </summary>
/// <returns></returns>
public ISession GetSession()
{
ISession session = null;
try
{
session = SessionFactoryUtils.GetSession(sessionFactory, false);
if (transactional) session.FlushMode = FlushMode.Auto;
}
catch (InvalidOperationException ioe)
{
if (log.IsDebugEnabled)
{
log.Debug("Failed to flush the session. Reason could be that the session has somehow already been closed.", ioe.GetBaseException());
}
session = sessionFactory.OpenSession();
if (transactional) session.FlushMode = FlushMode.Auto;
}
catch (Exception e)
{
if (log.IsDebugEnabled)
{
log.Debug("Failed to flush the session. Not sure what to do here, check exception: [" + e.Message + "]", e);
}
}
return session;
}
/// <summary>
/// Dispose the open session.
/// </summary>
public void Dispose()
{
if (transactional) Flush();
try
{
scope.Close();
scope.Dispose();
}
catch (Exception e)
{
if (log.IsDebugEnabled) log.Debug("Failed to close the session scope. Extract session and flush it if it is not null!", e);
ISession session = SessionFactoryUtils.GetSession(sessionFactory, false);
if(session != null)
{
if(session.FlushMode == FlushMode.Auto) session.Flush();
session.Close();
}
}
}
/// <summary>
/// Flushing and commiting data in transaction without closing the connection. Method can only be called manually.
/// </summary>
public void Flush()
{
ISession session = GetSession();
if (session != null && transactional)
{
session.Flush();
session.Clear();
}
}
}
Cheers,
Steinar.