- basicsample.zip
- BasicSample
- BasicSample.Core
- BasicSample.Data
- BasicSample.resharper
- BasicSample.resharper.user
- BasicSample.sln
- BasicSample.Tests
- BasicSample.Web
- Solution Items
- enterprisesample.zip
- EnterpriseSample
- EnterpriseSample.Core
- EnterpriseSample.Data
- EnterpriseSample.Presenters
- EnterpriseSample.resharper
- EnterpriseSample.resharper.user
- EnterpriseSample.sln
- EnterpriseSample.Tests
- EnterpriseSample.Web
- ProjectBase.Data
- ProjectBase.Utils
- Solution Items
- nhibernatebestpractices_src.zip
- NHibernateSample
- NHibernateSample.Core
- NHibernateSample.Data
- NHibernateSample.sln
- NHibernateSample.Tests
- NHibernateSample.Web
- Solution Items
- Iesi.Collections.dll
- log4net.dll
- NHibernate.dll
- NHibernate.Generics.dll
- nunit.framework.dll
|
using System;
using System.Collections;
using System.IO;
using System.Runtime.Remoting.Messaging;
using System.Web;
using NHibernate;
using NHibernate.Cache;
using NHibernate.Cfg;
using ProjectBase.Utils;
namespace ProjectBase.Data
{
/// <summary>
/// Handles creation and management of sessions and transactions. It is a singleton because
/// building the initial session factory is very expensive. Inspiration for this class came
/// from Chapter 8 of Hibernate in Action by Bauer and King. Although it is a sealed singleton
/// you can use TypeMock (http://www.typemock.com) for more flexible testing.
/// </summary>
public sealed class NHibernateSessionManager
{
#region Thread-safe, lazy Singleton
/// <summary>
/// This is a thread-safe, lazy singleton. See http://www.yoda.arachsys.com/csharp/singleton.html
/// for more details about its implementation.
/// </summary>
public static NHibernateSessionManager Instance {
get {
return Nested.NHibernateSessionManager;
}
}
/// <summary>
/// Private constructor to enforce singleton
/// </summary>
private NHibernateSessionManager() { }
/// <summary>
/// Assists with ensuring thread-safe, lazy singleton
/// </summary>
private class Nested
{
static Nested() { }
internal static readonly NHibernateSessionManager NHibernateSessionManager =
new NHibernateSessionManager();
}
#endregion
/// <summary>
/// This method attempts to find a session factory stored in <see cref="sessionFactories" />
/// via its name; if it can't be found it creates a new one and adds it the hashtable.
/// </summary>
/// <param name="sessionFactoryConfigPath">Path location of the factory config</param>
private ISessionFactory GetSessionFactoryFor(string sessionFactoryConfigPath) {
Check.Require(!string.IsNullOrEmpty(sessionFactoryConfigPath),
"sessionFactoryConfigPath may not be null nor empty");
// Attempt to retrieve a stored SessionFactory from the hashtable.
ISessionFactory sessionFactory = (ISessionFactory) sessionFactories[sessionFactoryConfigPath];
// Failed to find a matching SessionFactory so make a new one.
if (sessionFactory == null) {
Check.Require(File.Exists(sessionFactoryConfigPath),
"The config file at '" + sessionFactoryConfigPath + "' could not be found");
Configuration cfg = new Configuration();
cfg.Configure(sessionFactoryConfigPath);
// Now that we have our Configuration object, create a new SessionFactory
sessionFactory = cfg.BuildSessionFactory();
if (sessionFactory == null) {
throw new InvalidOperationException("cfg.BuildSessionFactory() returned null.");
}
sessionFactories.Add(sessionFactoryConfigPath, sessionFactory);
}
return sessionFactory;
}
/// <summary>
/// Allows you to register an interceptor on a new session. This may not be called if there is already
/// an open session attached to the HttpContext. If you have an interceptor to be used, modify
/// the HttpModule to call this before calling BeginTransaction().
/// </summary>
public void RegisterInterceptorOn(string sessionFactoryConfigPath, IInterceptor interceptor) {
ISession session = (ISession)ContextSessions[sessionFactoryConfigPath];
if (session != null && session.IsOpen) {
throw new CacheException("You cannot register an interceptor once a session has already been opened");
}
GetSessionFrom(sessionFactoryConfigPath, interceptor);
}
public ISession GetSessionFrom(string sessionFactoryConfigPath) {
return GetSessionFrom(sessionFactoryConfigPath, null);
}
/// <summary>
/// Gets a session with or without an interceptor. This method is not called directly; instead,
/// it gets invoked from other public methods.
/// </summary>
private ISession GetSessionFrom(string sessionFactoryConfigPath, IInterceptor interceptor) {
ISession session = (ISession)ContextSessions[sessionFactoryConfigPath];
if (session == null) {
if (interceptor != null) {
session = GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession(interceptor);
}
else {
session = GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession();
}
ContextSessions[sessionFactoryConfigPath] = session;
}
Check.Ensure(session != null, "session was null");
return session;
}
/// <summary>
/// Flushes anything left in the session and closes the connection.
/// </summary>
public void CloseSessionOn(string sessionFactoryConfigPath) {
ISession session = (ISession)ContextSessions[sessionFactoryConfigPath];
if (session != null && session.IsOpen) {
session.Flush();
session.Close();
}
ContextSessions.Remove(sessionFactoryConfigPath);
}
public ITransaction BeginTransactionOn(string sessionFactoryConfigPath) {
ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];
if (transaction == null) {
transaction = GetSessionFrom(sessionFactoryConfigPath).BeginTransaction();
ContextTransactions.Add(sessionFactoryConfigPath, transaction);
}
return transaction;
}
public void CommitTransactionOn(string sessionFactoryConfigPath) {
ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];
try {
if (HasOpenTransactionOn(sessionFactoryConfigPath)) {
transaction.Commit();
ContextTransactions.Remove(sessionFactoryConfigPath);
}
}
catch (HibernateException) {
RollbackTransactionOn(sessionFactoryConfigPath);
throw;
}
}
public bool HasOpenTransactionOn(string sessionFactoryConfigPath) {
ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];
return transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack;
}
public void RollbackTransactionOn(string sessionFactoryConfigPath) {
ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];
try {
if (HasOpenTransactionOn(sessionFactoryConfigPath)) {
transaction.Rollback();
}
ContextTransactions.Remove(sessionFactoryConfigPath);
}
finally {
CloseSessionOn(sessionFactoryConfigPath);
}
}
/// <summary>
/// Since multiple databases may be in use, there may be one transaction per database
/// persisted at any one time. The easiest way to store them is via a hashtable
/// with the key being tied to session factory. If within a web context, this uses
/// <see cref="HttpContext" /> instead of the WinForms specific <see cref="CallContext" />.
/// Discussion concerning this found at http://forum.springframework.net/showthread.php?t=572
/// </summary>
private Hashtable ContextTransactions {
get {
if (IsInWebContext()) {
if (HttpContext.Current.Items[TRANSACTION_KEY] == null)
HttpContext.Current.Items[TRANSACTION_KEY] = new Hashtable();
return (Hashtable)HttpContext.Current.Items[TRANSACTION_KEY];
}
else {
if (CallContext.GetData(TRANSACTION_KEY) == null)
CallContext.SetData(TRANSACTION_KEY, new Hashtable());
return (Hashtable)CallContext.GetData(TRANSACTION_KEY);
}
}
}
/// <summary>
/// Since multiple databases may be in use, there may be one session per database
/// persisted at any one time. The easiest way to store them is via a hashtable
/// with the key being tied to session factory. If within a web context, this uses
/// <see cref="HttpContext" /> instead of the WinForms specific <see cref="CallContext" />.
/// Discussion concerning this found at http://forum.springframework.net/showthread.php?t=572
/// </summary>
private Hashtable ContextSessions {
get {
if (IsInWebContext()) {
if (HttpContext.Current.Items[SESSION_KEY] == null)
HttpContext.Current.Items[SESSION_KEY] = new Hashtable();
return (Hashtable)HttpContext.Current.Items[SESSION_KEY];
}
else {
if (CallContext.GetData(SESSION_KEY) == null)
CallContext.SetData(SESSION_KEY, new Hashtable());
return (Hashtable)CallContext.GetData(SESSION_KEY);
}
}
}
private bool IsInWebContext() {
return HttpContext.Current != null;
}
private Hashtable sessionFactories = new Hashtable();
private const string TRANSACTION_KEY = "CONTEXT_TRANSACTIONS";
private const string SESSION_KEY = "CONTEXT_SESSIONS";
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.