关于NHibernate的一些代码

SessionManager

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Web;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Context;
 
namespace Northwind.Repositories
{
    /// <summary>
    /// A static (singleton) class to manage NHibernate.
    /// Manage NHibernate sessions using <see cref="Session"/>
    /// </summary>
    public sealed class SessionManager
    {
        private const string SESSIONKEY = "NHIBERNATE.SESSION";
        [ThreadStatic]
        private static ISession _Session; //this session is not used in web
        private readonly Configuration _configuration;
        private readonly ISessionFactory _sessionFactory;
 
        #region Constructor
 
        #region Singleton
        public static SessionManager Instance
        {
            get
            {
//#if !INSTANCE
                return Singleton.Instance;
//#else
//                return new SessionManager();
//#endif
            }
        }
 
//#if !INSTANCE
        private class Singleton
        {
            static Singleton() { }
            internal static readonly SessionManager Instance = new SessionManager();
        }
//#endif
        #endregion
 
        /// <summary>
        /// Initializes a new instance of the <see cref="SessionManager"/> class.
        /// </summary>
        private SessionManager()
        {
            _configuration = RestoreConfiguration();
            if (_configuration == null)
            {
                _configuration = new Configuration();
                BuildConfiguration();
            }
            //get the session factory
            _sessionFactory = Configuration.BuildSessionFactory();
        }
 
        private void BuildConfiguration()
        {
            Configuration.Configure(); //configure from the app.config
 
            Configuration.AddAssembly(GetType().Assembly);//default- mapping is in this assembly
            //other examples:
            //Configuration.AddFile("file.hbm.xml"); //add files
            //Configuration.AddAssembly(assembly); //add assembly
            //Configuration.AddAssembly(assemblyName); //add assembly by name
            //foreach (string assemblyName in assemblyNames) //add enumerable of assemblies
            //    Configuration.AddAssembly(assemblyName);
#if !DEBUG
            SaveConfiguration(Configuration);
#endif
        }
        #endregion
 
        #region Configuration Serialization
        //specify a full path if required
        private const string _configurationFilePath = "Configuration.save";
        private static void SaveConfiguration(Configuration configuration)
        {
            IFormatter serializer = new BinaryFormatter();
 
            using (Stream stream = File.OpenWrite(_configurationFilePath))
            {
                try
                {
                    serializer.Serialize(stream, configuration);
                }
                catch (UnauthorizedAccessException)
                {
                    Console.WriteLine("No write access to " + _configurationFilePath);
                }
            }
        }
 
        /// <summary>
        /// Optimization- you could deploy the serialization file.
        /// </summary>
        private static Configuration RestoreConfiguration()
        {
#if DEBUG
            return null;
#endif
            if (!File.Exists(_configurationFilePath)) return null;
            IFormatter serializer = new BinaryFormatter();
 
            using (Stream stream = File.OpenRead(_configurationFilePath))
            {
                return serializer.Deserialize(stream) as Configuration;
            }
        }
        #endregion
 
        #region NHibernate Setup
        /// <summary>
        /// Gets the <see cref="NHibernate.Cfg.Configuration"/>.
        /// </summary>
        internal Configuration Configuration { get { return _configuration; } }
 
        /// <summary>
        /// Gets the <see cref="NHibernate.ISessionFactory"/>
        /// </summary>
        internal ISessionFactory SessionFactory { get { return _sessionFactory; } }
 
        /// <summary>
        /// Closes the session factory.
        /// </summary>
        public void Close()
        {
            SessionFactory.Close();
        }
 
        internal static bool IsWeb { get { return (HttpContext.Current != null); } }
        #endregion
 
        #region NHibernate SessionContext (1.2+)
 
        /// <summary>
        /// Opens the conversation (if already existing, reuses it). Call this from Application_BeginPreRequestHandlerExecute
        /// </summary>
        /// <returns>A <see cref="NHibernate.ISession"/></returns>
        public ISession OpenConversation()
        {
            //you must set <property name="current_session_context_class">web</property> (or thread_static etc)
            ISession session = Session; //get the current session (or open one). We do this manually, not using SessionFactory.GetCurrentSession()
            //for session per conversation (otherwise remove)
            session.FlushMode = FlushMode.Never; //Only save on session.Flush() - because we need to commit on unbind in PauseConversation
            session.BeginTransaction(); //start a transaction
            CurrentSessionContext.Bind(session); //bind it
            return session;
        }
 
        /// <summary>
        /// Ends the conversation. If an exception occurs, rethrows it ensuring session is closed. Call this (or <see cref="PauseConversation"/> if session per conversation) from Application_PostRequestHandlerExecute
        /// </summary>
        public void EndConversation()
        {
            ISession session = CurrentSessionContext.Unbind(SessionFactory);
            if (session == null) return;
            try
            {
                session.Flush();
                session.Transaction.Commit();
            }
            catch (Exception)
            {
                session.Transaction.Rollback();
                throw;
            }
            finally
            {
                session.Close();
            }
        }
 
        /// <summary>
        /// Pauses the conversation. Call this (or <see cref="EndConversation"/>) from Application_EndRequest
        /// </summary>
        public void PauseConversation()
        {
            ISession session = CurrentSessionContext.Unbind(SessionFactory);
            if (session == null) return;
            try
            {
                session.Transaction.Commit(); //with flushMode=Never, this closes connections but doesn't flush
            }
            catch (Exception)
            {
                session.Transaction.Rollback();
                throw;
            }
            //we don't close the session, and it's still in Asp SessionState
        }
        #endregion
 
        #region NHibernate Sessions
 
        /// <summary>
        /// Explicitly open a session. If you have an open session, close it first.
        /// </summary>
        /// <returns>The <see cref="NHibernate.ISession"/></returns>
        public ISession OpenSession()
        {
            ISession session = SessionFactory.OpenSession();
            if (IsWeb)
                HttpContext.Current.Items.Add(SESSIONKEY, session);
            else
                _Session = session;
            return session;
        }
 
        /// <summary>
        /// Gets the current <see cref="NHibernate.ISession"/>. Although this is a singleton, this is specific to the thread/ asp session. If you want to handle multiple sessions, use <see cref="OpenSession"/> directly. If a session it not open, a new open session is created and returned.
        /// </summary>
        /// <value>The <see cref="NHibernate.ISession"/></value>
        public ISession Session
        {
            get
            {
                //use threadStatic or asp session.
                ISession session = IsWeb ? HttpContext.Current.Items[SESSIONKEY] as ISession : _Session;
                //if using CurrentSessionContext, SessionFactory.GetCurrentSession() can be used
 
                //if it's an open session, that's all
                if (session != null && session.IsOpen)
                    return session;
 
                //if not open, open a new session
                return OpenSession();
            }
        }
        #endregion
 
    }
}

NHibernateModule:

using System;
using System.Web;
using NHibernate;
using NHibernate.Context;
using Northwind;
 
/// <summary>
/// A simple HttpModule which loads NHibernate session
/// </summary>
public class NHibernateModule : IHttpModule
{
    #region Implementation of IHttpModule
 
    /// <summary>
    /// Initializes a module and prepares it to handle requests.
    /// </summary>
    /// <param name="context">An <see cref="T:System.Web.HttpApplication"/> that provides access to the methods, properties, and events common to all application objects within an ASP.NET application 
    /// </param>
    public void Init(HttpApplication context)
    {
        context.BeginRequest += context_BeginRequest;
        context.EndRequest += context_EndRequest;
    }
 
    private static void context_BeginRequest(object sender, EventArgs e)
    {
        //use my session manager
        ISession session = SessionManager.Instance.OpenSession();
        CurrentSessionContext.Bind(session);
    }
 
    private static void context_EndRequest(object sender, EventArgs e)
    {
        ISessionFactory sessionFactory = SessionManager.Instance.SessionFactory;
        ISession session = CurrentSessionContext.Unbind(sessionFactory);
 
        if (session == null) return;
        if (session.Transaction != null)
        {
            if (session.Transaction.IsActive)
            {
                //if there is an active session, commit it
                session.Transaction.Commit();
            }
            else
            {
                //
                session.Transaction.Rollback();
            }
        }
 
        session.Close();
    }
 
    /// <summary>
    /// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>.
    /// </summary>
    public void Dispose()
    {
    }
 
    #endregion
}
Web.config

It needs to include these lines...

<configuration>
   <!-- IIS 6 -->
    <system.web>
         <httpModules>
            <add name="NHibernateModule" type="NHibernateModule"/>
        </httpModules>
     </system.web>
     <!-- IIS 7 and Cassini. -->
    <system.webServer>
         <modules>
            <add name="NHibernateModule" type="NHibernateModule"/>
        </modules>
    </system.webServer>
</configuration>
NHibernate configuration

The config file needs to include this line.

<property name="current_session_context_class">
web
</property>

  GenericRepository:

using System;
using System.Collections.Generic;
using NHibernate;
 
namespace Northwind
{
    /// <summary>
    /// A generic repository. Normally this would be a base class of customized entity repositories- not directly exposed.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <remarks>
    /// All operations are wrapped with <see cref="TransactionRequired"/>. If there is NO open transaction, they open a transaction and commit immediately. If there is an open transaction, nothing is commited, so you should commit at a higher level.
    /// </remarks>
    public class GenericRepository<T> where T : new()
    {
        protected ISession Session
        {
            get { return SessionManager.Instance.Session; }
        }
 
        #region Read
        /// <summary>
        /// Loads the specified id. Throws an exception if not in database.
        /// </summary>
        public T Load(object id)
        {
            using (TransactionRequired transaction = new TransactionRequired())
            {
                return Session.Load<T>(id);
            }
        }
 
        /// <summary>
        /// Gets the Id. Returns null if there is no matching row
        /// </summary>
        public T GetById(object id)
        {
            using (TransactionRequired transaction = new TransactionRequired())
            {
                return Session.Get<T>(id);
            }
        }
 
        /// <summary>
        /// Finds all records. Consider <see cref="FindPage"/> for large result sets.
        /// </summary>
        public ICollection<T> FindAll()
        {
            using (TransactionRequired transaction = new TransactionRequired())
            {
                return Session.CreateCriteria(typeof(T)).List<T>();
            }
        }
 
        /// <summary>
        /// Counts the number of records.
        /// </summary>
        public int Count()
        {
            ICriteria criteria = Session.CreateCriteria(typeof(T));
            using (TransactionRequired transaction = new TransactionRequired())
            {
                return criteria.SetProjection(NHibernate.Criterion.Projections.RowCount()).UniqueResult<int>();
            }
        }
 
        /// <summary>
        /// Finds records by page.
        /// </summary>
        /// <param name="pageStartRow">The page start row.</param>
        /// <param name="pageSize">Size of the page.</param>
        public IList<T> FindPage(int pageStartRow, int pageSize)
        {
            ICriteria criteria = Session.CreateCriteria(typeof(T));
            criteria.SetFirstResult(pageStartRow);
            criteria.SetMaxResults(pageSize);
            using (TransactionRequired transaction = new TransactionRequired())
            {
                return criteria.List<T>();
            }
        }
 
        /// <summary>
        /// Finds records by page, sorted.
        /// </summary>
        public IList<T> FindSortedPage(int pageStartRow, int pageSize, string sortBy, bool descending)
        {
            ICriteria criteria = Session.CreateCriteria(typeof(T));
 
            if (descending)
                criteria.AddOrder(NHibernate.Criterion.Order.Desc(sortBy));
            else
                criteria.AddOrder(NHibernate.Criterion.Order.Asc(sortBy));
 
            criteria.SetFirstResult(pageStartRow);
            criteria.SetMaxResults(pageSize);
            using (TransactionRequired transaction = new TransactionRequired())
            {
                return criteria.List<T>();
            }
        }
        #endregion
 
        #region Update
        /// <summary>
        /// Saves the specified object within a transaction.
        /// </summary>
        public void Save(T entity)
        {
            using (TransactionRequired transaction = new TransactionRequired())
            {
                Session.Save(entity);
                transaction.Commit(); //flush to database
            }
        }
 
        /// <summary>
        /// Saves the specified object within a transaction.
        /// </summary>
        public void SaveOrUpdate(T entity)
        {
            using (TransactionRequired transaction = new TransactionRequired())
            {
                Session.SaveOrUpdate(entity);
                transaction.Commit(); //flush to database
            }
        }
 
        /// <summary>
        /// Deletes the specified object within a transaction.
        /// </summary>
        public void Delete(T entity)
        {
            using (TransactionRequired transaction = new TransactionRequired())
            {
                Session.Delete(entity);
                transaction.Commit(); //flush to database
            }
        }
        #endregion
    }
}

TransactionRequired:

using System;
using NHibernate;
 
namespace Northwind.Repositories
{
    /// <summary>
    /// Ensure a code block is transactional.
    /// If the session transaction is not open, create a transaction; otherwise there is an existing transaction so don't do anything.
    /// </summary>
    /// <remarks>
    /// Equivalent to <see cref="System.Transactions.TransactionScope"/> with default <see cref="System.Transactions.TransactionScopeOption"/> value <c>Required</c> (enlist in enclosing transaction or create a new one if it doesn't exist).
    /// </remarks>
    public sealed class TransactionRequired : IDisposable
    {
        private const string TRANSACTIONKEY = "NHIBERNATE.TRANSACTION";
        private ITransaction _transaction;
        private bool _shouldCommit;
        private bool _completed;
 
        #region Constructor
        public TransactionRequired(ISession session)
        {
            if (session == null) throw new ArgumentNullException("session");
            _transaction = session.Transaction; //equal to Transaction.Current
            if (!IsOpenTransaction(_transaction))
            {
                _transaction = session.BeginTransaction();
                ShouldCommit = true;
            }
        }
        #endregion
 
        #region NHibernate Transactions
 
        /// <summary>
        /// Gets or sets a value indicating whether this transaction should commit. If there is an open transaction, by default calling Commit will not do anything- it will leave the transaction open.
        /// </summary>
        /// <value><c>true</c> if should commit; otherwise, <c>false</c>.</value>
        public bool ShouldCommit
        {
            get { return _shouldCommit; }
            set { _shouldCommit = value; }
        }
 
        public void Commit()
        {
            if (!ShouldCommit) return;
 
            if (_completed)
                throw new InvalidOperationException("The current transaction is already committed. You should dispose the transaction.");
 
            _completed = true;
 
            try
            {
                if (IsOpenTransaction(_transaction))
                {
                    _transaction.Commit();
                    _transaction = null;
                }
            }
            catch (HibernateException)
            {
                RollbackTransaction();
                throw;
            }
        }
 
        public void RollbackTransaction()
        {
            if (!ShouldCommit) return;
            _completed = true;
 
            if (IsOpenTransaction(_transaction))
                _transaction.Rollback();
            _transaction = null;
        }
 
        private static bool IsOpenTransaction(ITransaction transaction)
        {
            return transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack;
        }
 
        #endregion
 
 
        #region IDisposable Members
 
        public void Dispose()
        {
            if (!ShouldCommit) return;
            RollbackTransaction();
        }
 
        #endregion
    }
}

原文出处:http://www.martinwilley.com/net/code/nhibernate/index.html

posted @ 2013-08-07 20:38  狼性法则  阅读(1102)  评论(1编辑  收藏  举报