MVC3+NHibernate项目实战(二) :数据库访问层

我们现在使用NHibernate一步一步来构建数据库访问层.

一.首先建立Blog.Model:实体层项目

(1)先建立EntityBase实体基类,然后所有的实体都继承该类;

View Code
namespace Blog.Model
{
    public class EntityBase
    {
        public virtual int Id { get; set; }
       public virtual bool IsDelete { get; set; }
       public virtual DateTime CreateDate { get; set; }
       public virtual int Version { get; set; }
    }
}

Id:使用int值作为id;

IsDelete:是否删除;

CreateDate:创建时间;

Version:NHibernate中作并发控制;

(2)建立实体User

View Code
namespace Blog.Model.Entities
{    
    public class User:EntityBase
    {
        public virtual int Id{ get;set; }
        public virtual string UserName{ get;set; }
        public virtual string Password{ get;set; }
        public virtual string NickName{ get;set; }
        public virtual bool Gender{ get;set; }
        public virtual DateTime Birthday{ get;set; }
        public virtual string Email{ get;set; }
        public virtual string Address{ get;set; }
        public virtual string Phone{ get;set; }
        public virtual string QQ{ get;set; }
        public virtual bool IsActive{ get;set; }
    }
}

注意:属性都加上virtual关键字

(3)建立实体xml映射文件

View Code
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Blog.Model" assembly="Blog.Model">
    <class name="Blog.Model.Entities.User, Blog.Model" table="`User`">
        <id name="Id" type="Int32" unsaved-value="null">
            <column name="UserId" length="4" sql-type="int" not-null="true" unique="true" index="PK_USER"/>
            <generator class="native" />
        </id>
        <version name="Version" column="Version" type="integer" unsaved-value="0"/>
        <property name="UserName" type="String">
            <column name="UserName" length="50" sql-type="nvarchar" not-null="false"/>
        </property>
        <property name="Password" type="String">
            <column name="Password" length="50" sql-type="nvarchar" not-null="false"/>
        </property>
        <property name="NickName" type="String">
            <column name="NickName" length="50" sql-type="nvarchar" not-null="false"/>
        </property>
        <property name="Gender" type="Boolean">
            <column name="Gender" length="1" sql-type="bit" not-null="false"/>
        </property>
        <property name="Birthday" type="DateTime">
            <column name="Birthday" length="8" sql-type="datetime" not-null="false"/>
        </property>
        <property name="Email" type="String">
            <column name="Email" length="50" sql-type="varchar" not-null="false"/>
        </property>
        <property name="Address" type="String">
            <column name="Address" length="50" sql-type="nvarchar" not-null="false"/>
        </property>
        <property name="Phone" type="String">
            <column name="Phone" length="15" sql-type="varchar" not-null="false"/>
        </property>
        <property name="QQ" type="String">
            <column name="QQ" length="10" sql-type="varchar" not-null="false"/>
        </property>
        <property name="IsActive" type="Boolean">
            <column name="IsActive" length="1" sql-type="bit" not-null="false"/>
        </property>
        <property name="CreateDate" type="DateTime">
            <column name="CreateDate" length="8" sql-type="datetime" not-null="false"/>
        </property>
        <property name="IsDelete" type="Boolean">
            <column name="IsDelete" length="1" sql-type="bit" not-null="false"/>
    </class>
</hibernate-mapping>

注意:hbmXML映射文件,属性必须设置为"嵌入的资源";XML中的Version字段必须在Id字段之后

 

NHibernate  Id生成方式选择
映射文件id生成选择:<generator class="native" />
Assigned : 主键由外部程序负责生成,无需Hibernate参与,如Guid
identity : 采用数据库提供的主键生成机制
native
 由Hibernate根据底层数据库自行判断采用identity、hilo、sequence其中一种作为主键生成方式。
我上面只是列举了常用的几种,具体可以自己查找;
我们实体层的工作基本已经完成
 
二.建立NHibernate配置文件
 
我们使用的是单个的配置文件方式,配置文件名hibernate.cfg.xml;
View Code
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration  xmlns="urn:nhibernate-configuration-2.2" >
  <session-factory name="NHibernateWeb">
    <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
    <property name="connection.connection_string">
      Data Source=.\SQLEXPRESS;Initial Catalog=BlogDB;Integrated Security=True;Pooling=False
    </property>
    <property name="adonet.batch_size">10</property>
    <property name="show_sql">true</property>
    <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
    <property name="command_timeout">10</property>
    <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
    <mapping assembly="Blog.Model"/>
  </session-factory>
</hibernate-configuration>

三.建立Blog.Repository:数据访问层

 

(1)新建接口IRepository

View Code
namespace Blog.Repository
{
    public interface IRepository<T, TId> where T : EntityBase
    {
        T Load(TId id);
        T Get(TId id);
        IList<T> GetAll();
        IList<T> FindForPage(int index, int count);
        IList<T> Find(Expression<Func<T, bool>> query);
        T FindForSingle(Expression<Func<T, bool>> query);
        IList<T> HQLQuery(string query);
        TId Save(T entity);
        void SaveOrUpdate(T entity);
        void Update(T entity);
        void Delete(T t);
        void PhysicsDelete(TId id);
    }
}

 

(2)新建Repository基类

View Code
namespace Blog.Repository
{
    public abstract class Repository<T, TId> where T : EntityBase
    {
        private IUnitOfWork _uow;
        public Repository(IUnitOfWork uow)
        {
            _uow = uow;
        }
        protected virtual ISession Session
        {
            get { return NHSessionFactory.CreateSession(); }
        }

        /// <summary>
        /// 根据Id延迟加载获取实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual T Load(TId id)
        {
            return Session.Load<T>(id);
        }

        /// <summary>
        /// 根据Id获取实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual T Get(TId id)
        {
            return Session.Get<T>(id);
        }

        /// <summary>
        /// 获取所有实体
        /// </summary>
        /// <returns></returns>
        public virtual IList<T> GetAll()
        {
            return Session.CreateCriteria(typeof(T)).List<T>();//使用Criteria
            //return Session.Query<T>().ToList();
            //return Session.QueryOver<T>().List();//使用QueryOver linq
        }

        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="index">index=(pageNum-1)*pageCount</param>
        /// <param name="count">每页的条数pageCount</param>
        /// <returns></returns>
        public IList<T> FindForPage(int index, int count)
        {
            return Session.CreateCriteria(typeof(T)).SetMaxResults(count).SetFirstResult(index).List<T>();
        }

        /// <summary>
        /// lambda表达式获取
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public IList<T> Find(Expression<Func<T, bool>> query)
        {
            return Session.QueryOver<T>().Where(query).List();
        }

        /// <summary>
        /// lambda表达式获取单个实体
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public T FindForSingle(Expression<Func<T, bool>> query)
        {
            return Session.Query<T>().SingleOrDefault(query);
        }


        /// <summary>
        /// HQL查询
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public IList<T> HQLQuery(string query)
        {
           return Session.CreateQuery(query).List<T>();
        }

        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual TId Save(T entity)
        {
            return (TId)Session.Save(entity);
        }

        /// <summary>
        /// 保存或更新
        /// </summary>
        /// <param name="entity"></param>
        public virtual void SaveOrUpdate(T entity)
        {
            Session.SaveOrUpdate(entity);
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="entity"></param>
        public virtual void Update(T entity)
        {
            Session.Update(entity);
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        public virtual void PhysicsDelete(TId id)
        {
            var entity = Get(id);
            Session.Delete(entity);
        }

        public void Delete(T t)
        {
            t.IsDelete = true;
            Update(t);
        }
    }
}

 

(3)建立对应的实体的数据访问接口IUserRepository,该接口实现了IRepository

View Code
namespace Blog.Repository
{    
    public interface IUserRepository:IRepository<User,int>
    {
    }
}

 

(4)建立实体的数据访问实现体

View Code
namespace Blog.Repository
{    
    public class UserRepository:Repository<User,int>,IUserRepository
    {
        public UserRepository(IUnitOfWork uow)
           : base(uow)
        {}
    }
}

 

(5)Unit of Work模式,从上面的Repository基类可以看到,我们已经注入了该模式的实现;

   1.建立IUnitOfWork接口

namespace Blog.Repository
{
    public interface IUnitOfWork
    {
        void Commit();
    }
}

 

 2.建立NHUnitOfWork类,实现IUnitOfWork接口

View Code
namespace Blog.Repository
{
    public class NHUnitOfWork : IUnitOfWork
    {
        public ISession session
        {
            get { return NHSessionFactory.CreateSession(); }
        }
      

        public void Commit()
        {
            using (ITransaction transaction = session.BeginTransaction())
            {
                try
                {
                    session.Flush();
                    transaction.Commit(); 
                }
                catch (Exception ex)
                {
                    transaction.Rollback();
                    throw;
                }
            }
        }
    }
}

 

 (6)NHibernate的Session管理与初始化

为了合理控制Session的生命周期,在.netMVC中我们把Session的生命周期绑定在一次Action里;

  1.建立接口ISessionStorage;

View Code
namespace Blog.Repository.SessionStorage
{
    public interface ISessionStorage
    {
        ISession Get();
        void Set(ISession value);
    }
}

 

  2.新建一个类HttpSessionStorage实现接口ISessionStorage; 

 

    public class HttpSessionStorage:ISessionStorage
    {
        private string sessionKey = "NhbSession";
        public NHibernate.ISession Get()
        {
            ISession session = null;
            if (HttpContext.Current.Items.Contains(sessionKey))
                session = (ISession)HttpContext.Current.Items[sessionKey];
            return session;
        }

        public void Set(ISession value)
        {
            if (value != null)
            {
                if (HttpContext.Current != null)
                {
                    HttpContext.Current.Items.Add(sessionKey, value);
                }               
            }
        }
    }

  

  3.新建一个工厂类,获取NHibernate的session

View Code
namespace Blog.Repository.SessionStorage
{
    public static class NHSessionFactory
    {
        private static object locker = new object();
        private static Configuration _configuration = null;
        private static ISessionFactory _sessionFactory = null;

        private static ISessionStorage SessionStorage{get;set;}
        public static void InitSessionFactory(ISessionStorage sessionStorage)
        {
            SessionStorage = sessionStorage;//使用ioc容器注入
        }

        private static void CreateConfiguration()
        {          
            _configuration = new Configuration().Configure();
        }

        public static Configuration Configuration
        {
            get
            {
                lock (locker)
                {
                    if (_configuration == null)
                    {
                        CreateConfiguration();
                    }
                    return _configuration;
                }
            }
            set { _configuration = value; }
        }

        internal static ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                {
                    if (Configuration == null)
                    {
                        CreateConfiguration();
                    }
                    lock (locker)
                    {
                        _sessionFactory = Configuration.BuildSessionFactory();
                    }
                }
                return _sessionFactory;
            }
        }

        public static ISession CreateSession()
        {
            ISession s = SessionStorage.Get();
            if (s == null)
            {
                s = SessionFactory.OpenSession();
                SessionStorage.Set(s);
            }
            return s;
        }
    }
}

 注意要在 void Application_Start()进行初始化

  如下代码

NHSessionFactory.InitSessionFactory(container.Resolve<ISessionStorage>());//NHibernate session

这样我们的数据库访问层基本完成了!!

posted @ 2012-09-18 09:37  Jeff.Zhong  阅读(2210)  评论(2编辑  收藏  举报