NHibernate3.2+Asp.net MVC3+Extjs 4.0.2项目实践(二): NHibernate数据访问层实现

    关于NHibernate的ORM映射可以通过Hbm映射文件来完成,代码生成工具使得这一步骤变得简化;而NHibernate3.2版本集成Mapping-By-Code(代码映射),不同于其他映射方式,具体可以参考李永京博客(NHibernate剖析:Mapping篇之Mapping-By-Code),此处不再赘述;Mapping-By-Code采用手动配置实体映射,顾名思义会增加程序代码编写量,而且数据库表关系映射(ont-to-many, many-to-one,many-to-many)编写比较复杂,所以我摒弃这种方式而采用了Mindscape NHibernate Model Designer设计工具。为此,首先介绍一下NHibernate数据访问层,Web.config文件配置、NHibernate Configuration类和Session Manager类。

Web.config
隐藏行号 复制代码
  1. <appSettings>
    
  2.     <add key="ClientValidationEnabled" value="true"/> 
    
  3.     <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
    
  4.     <add key="TESZConnectionString" value="User id=sa;Password=sql123!!;data source=localhost;persist security info=True;initial catalog=TESZ_NEW;"/>
    
  5.   </appSettings>
    
  6. 
    

    Web.config是采用appSettings来设置数据库connection string,而非NHiberate标准配置。

NHibernateCfg.cs
隐藏行号 复制代码
  1. public static class NHibernateCfg
    
  2.     {
    
  3.         private static string _ConnectionString;
    
  4. 
    
  5.         public static Configuration GetConfiguration()
    
  6.         {
    
  7.             _ConnectionString = System.Configuration.ConfigurationManager.AppSettings["TESZConnectionString"].ToString();
    
  8. 
    
  9.             var configure = new Configuration();
    
  10. 
    
  11.             configure.SessionFactoryName("TESZ_NEW");            
    
  12.            
    
  13.             configure.DataBaseIntegration(db =>
    
  14.             {
    
  15.                 db.Dialect<MsSql2005Dialect>();
    
  16.                 db.Driver<SqlClientDriver>();
    
  17.                 db.ConnectionString = _ConnectionString;
    
  18.             });
    
  19. 
    
  20.             ApplyConfiguration(configure);
    
  21. 
    
  22.             return configure;
    
  23.         }
    
  24. 
    
  25.         public static void ApplyConfiguration(Configuration configuration)
    
  26.         {
    
  27.             configuration.AddXml(Location_Country.MappingXml.ToString());
    
  28.             configuration.AddXml(Location_StateProvince.MappingXml.ToString());
    
  29.             configuration.AddXml(Location_City.MappingXml.ToString());
    
  30.             configuration.AddXml(Common_Date.MappingXml.ToString());
    
  31.             configuration.AddXml(System_Purview.MappingXml.ToString());
    
  32.             configuration.AddAssembly(typeof(NHibernateCfg).Assembly);
    
  33.         }
    
  34.     }
    

     此处在NHibernateCfg类中进行数据库连接属性的配置,并把由Mindscape NHibernate Model Designer工具生成的实体类中的MappingXml配置给Configuration,来进行ORM映射。

SessionManager.cs
隐藏行号 复制代码
  1. /// <summary>
    
  2.     /// 使用 NHibernate 操作数据库的Session
    
  3.     /// </summary>
    
  4.     public sealed class SessionManager 
    
  5.     {
    
  6.         private const string CurrentSessionKey = "nhibernate.current_session";
    
  7.         private static readonly ISessionFactory sessionFactory;
    
  8. 
    
  9.         private static Configuration conf = null;
    
  10.         private static ModelMapper mapper = null;
    
  11. 
    
  12.         static SessionManager()
    
  13.         {
    
  14.             mapper = new ModelMapper();
    
  15.             if (sessionFactory == null)
    
  16.             {
    
  17.                 conf = NHibernateCfg.GetConfiguration();
    
  18. 
    
  19.                 sessionFactory = conf.BuildSessionFactory();
    
  20.             }
    
  21.         }
    
  22. 
    
  23.         public static ISession GetCurrentSession()
    
  24.         {
    
  25.             HttpContext context = HttpContext.Current;
    
  26.             ISession currentSession = context.Items[CurrentSessionKey] as ISession;
    
  27. 
    
  28.             if (currentSession == null)
    
  29.             {
    
  30.                 currentSession = sessionFactory.OpenSession();
    
  31.                 context.Items[CurrentSessionKey] = currentSession;
    
  32.             }
    
  33.             else
    
  34.             {
    
  35.                 currentSession = sessionFactory.OpenSession();
    
  36.             }
    
  37. 
    
  38.             return currentSession;
    
  39.         }
    
  40. 
    
  41.         public static void CreateDataTable()
    
  42.         {
    
  43.             //配置数据库a
    
  44.             SchemaMetadataUpdater.QuoteTableAndColumns(conf);
    
  45.             //创建数据库
    
  46.             new SchemaExport(conf).Create(false, true);
    
  47.         }
    
  48. 
    
  49.         public static void DropDataTable()
    
  50.         {
    
  51.             //配置数据库
  52.             SchemaMetadataUpdater.QuoteTableAndColumns(conf);
    
  53.             //删除数据库
  54.             new SchemaExport(conf).Drop(false, true);
    
  55.         }
    
  56. 
    
  57.         public static void CloseSession()
    
  58.         {
    
  59.             HttpContext context = HttpContext.Current;
    
  60.             ISession currentSession = context.Items[CurrentSessionKey] as ISession;
    
  61. 
    
  62.             if (currentSession == null)
    
  63.             {
    
  64.                 // No current session
    
  65.                 return;
    
  66.             }
    
  67.             currentSession.Close();
    
  68.             context.Items.Remove(CurrentSessionKey);
    
  69.         }
    
  70. 
    
  71.         public static void CloseSessionFactory()
    
  72.         {
    
  73.             if (sessionFactory != null)
    
  74.             {
    
  75.                 sessionFactory.Close();
    
  76.             }
    
  77.         }
    
  78.     }
    

     以上是NHibernate Session管理类。

     接着就该讲如何通过Mindscape NHibernate Model Designer工具生成实体类了。具体方法是:选择新建项,在“已安装的模版”的数据分类下选择NHibernate Model,然后从“服务器资源管理器”中拖拽表至Mindscape设计器中,并可以通过NHibernate Model工具栏的Model->Entities->实体类的属性进行实体类的更名。生成的实体类如下图:

Location_Country.cs
隐藏行号 复制代码
  1. [System.CodeDom.Compiler.GeneratedCode("NHibernateModelGenerator", "1.0.0.0")]
    
  2.   public partial class Location_Country
    
  3.   {
    
  4.     public virtual int CountryId { get; set; }
    
  5.     public virtual string CountryCode1 { get; set; }
    
  6.     public virtual string CountryCode2 { get; set; }
    
  7.     public virtual System.Nullable<System.DateTime> ModifiedDate { get; set; }
    
  8.     public virtual string ModifiedBy { get; set; }
    
  9.     public virtual string CountryDialCode { get; set; }
    
  10.     public virtual string CountryName { get; set; }
    
  11. 
    
  12.     private IList<Location_StateProvince> _locationStateProvinces = new List<Location_StateProvince>();
    
  13. 
    
  14.     public virtual IList<Location_StateProvince> LocationStateProvinces
    
  15.     {
    
  16.       get { return _locationStateProvinces; }
    
  17.       set { _locationStateProvinces = value; }
    
  18.     }
    
  19. 
    
  20.     static partial void CustomizeMappingDocument(System.Xml.Linq.XDocument mappingDocument);
    
  21. 
    
  22.     public static System.Xml.Linq.XDocument MappingXml
    
  23.     {
    
  24.       get
    
  25.       {
    
  26.         var mappingDocument = System.Xml.Linq.XDocument.Parse(@"<?xml version='1.0' encoding='utf-8' ?>
    
  27. <hibernate-mapping xmlns='urn:nhibernate-mapping-2.2'
    
  28.                    assembly='" + typeof(Location_Country).Assembly.GetName().Name + @"'
    
  29.                    namespace='TESZ.Data.Model'
    
  30.                    >
    
  31.   <class name='Location_Country'
    
  32.          table='`Location_Country`'
    
  33.          >
    
  34.     <id name='CountryId'
    
  35.         column='`CountryId`'
    
  36.         >
    
  37.       <generator class='identity'>
    
  38.       </generator>
    
  39.     </id>
    
  40.     <property name='CountryCode1'
    
  41.               column='`CountryCode1`'
    
  42.               />
    
  43.     <property name='CountryCode2'
    
  44.               column='`CountryCode2`'
    
  45.               />
    
  46.     <property name='ModifiedDate'
    
  47.               column='`ModifiedDate`'
    
  48.               />
    
  49.     <property name='ModifiedBy'
    
  50.               column='`ModifiedBy`'
    
  51.               />
    
  52.     <property name='CountryDialCode'
    
  53.               column='`CountryDialCode`'
    
  54.               />
    
  55.     <property name='CountryName'
    
  56.               column='`CountryName`'
    
  57.               />
    
  58.     <bag name='LocationStateProvinces'
    
  59.           inverse='true'
    
  60.           >
    
  61.       <key column='`CountryId`' />
    
  62.       <one-to-many class='Location_StateProvince' />
    
  63.     </bag>
    
  64.   </class>
    
  65. </hibernate-mapping>");
    
  66.         CustomizeMappingDocument(mappingDocument);
    
  67.         return mappingDocument;
    
  68.       }
    
  69.     }
    
  70.   }
    

      此处请注意一下三项(以上实体类已经经过修改):

    1.自动生成的实体类文件中,需要删除ConfigurationHelper类,因为之前在NHibernateCfg中已经配置MappingXml;

            2.实体类中的internal static System.Xml.Linq.XDocument MappingXml的internal需改为public,否则NHibernateCfg的configuration.AddXml(Location_Country.MappingXml.ToString());会报错;

    3.如果数据表有one-to-many关系,则必有many-to-one关系,MappingXml中会自动生成;比如<many-to-one name='Country' class='Location_Country' column='`CountryId`' />,则需要在其中添加lazy='false' 属性,否则实体类Location_StateProvince通过mant-to-one关系访问实体Location_Country时会抛出异常;

            4.如果数据表结构发生变化,可以在Mindscape设计器中以Update Model from Database来更新实体类,之后还要重复以上三个步骤。

  如需自动生成one-to-many和many-to-one关系,则在进行数据库创建时,要配置数据表对应关系,如下图:

数据表关系设计

Snap3

  如此,就完成了实体类的编写。

  最后简单讲一下数据访问接口和接口实现,在这儿我就不仔细说了,直接贴代码吧!

ILocation_CountryRepository.cs
隐藏行号 复制代码
  1. public interface ILocation_CountryRepository
    
  2.     {
    
  3.         IList<Location_Country> FindAll();
    
  4.         IList<Location_Country> FindIndistinct(Country_Query_Index country_Query_Index , object o);
    
  5.         bool Create(Location_Country location_Country);
    
  6.         bool Update(Location_Country location_Country);
    
  7.         bool Delete(Location_Country location_Country);
    
  8.         Location_Country FindOne(Country_Query_Index country_Query_Index, object o);
    
  9.     }
    

  通过QueryOver和Lambda表达式进行数据查询

Location_CountryRepository.cs
隐藏行号 复制代码
  1. public class Location_CountryRepository : ILocation_CountryRepository
    
  2.     {
    
  3.         public Location_CountryRepository()
    
  4.         {
    
  5.         }
    
  6. 
    
  7.         public IList<Location_Country> FindAll()
    
  8.         {
    
  9.             using (var session = SessionManager.GetCurrentSession())
    
  10.             {
    
  11.                 var query = session.QueryOver<Location_Country>()
    
  12.                 .OrderBy(p => p.CountryId).Asc
    
  13.                 .List();
    
  14. 
    
  15.                 return query;
    
  16.             }
    
  17.         }
    
  18. 
    
  19.         //模糊查询
    
  20.         public IList<Location_Country> FindIndistinct(Country_Query_Index country_Query_Index, object o)
    
  21.        {
    
  22.            using (var session = SessionManager.GetCurrentSession())
    
  23.            {
    
  24.                IList<Location_Country> query=null;
    
  25. 
    
  26.                switch (country_Query_Index)
    
  27.                {
    
  28.                    case Country_Query_Index.CountryName:
    
  29.                        {
    
  30.                            query = session.QueryOver<Location_Country>()
    
  31.                                .WhereRestrictionOn(k => k.CountryName).IsLike(o)
    
  32.                                .OrderBy(p => p.CountryId).Asc
    
  33.                                .List();
    
  34. 
    
  35.                            break;
    
  36.                        }
    
  37.                    case Country_Query_Index.Code1:
    
  38.                        {
    
  39.                            query = session.QueryOver<Location_Country>()
    
  40.                                .WhereRestrictionOn(k => k.CountryCode1).IsLike(o)
    
  41.                                .OrderBy(p => p.CountryId).Asc
    
  42.                                .List();
    
  43. 
    
  44.                            break;
    
  45.                        }
    
  46.                    case Country_Query_Index.Code2:
    
  47.                        {
    
  48.                            query = session.QueryOver<Location_Country>()
    
  49.                                .WhereRestrictionOn(k => k.CountryCode2).IsLike(o)
    
  50.                                .OrderBy(p => p.CountryId).Asc
    
  51.                                .List();
    
  52. 
    
  53.                            break;
    
  54.                        }
    
  55.                    case Country_Query_Index.DialCode:
    
  56.                        {
    
  57.                            query = session.QueryOver<Location_Country>()
    
  58.                                .WhereRestrictionOn(k => k.CountryDialCode).IsLike(o)
    
  59.                                .OrderBy(p => p.CountryId).Asc
    
  60.                                .List();
    
  61. 
    
  62.                            break;
    
  63.                        }
    
  64.                }
    
  65. 
    
  66.                return query;
    
  67.            }
    
  68.        }
    
  69. 
    
  70.         public Location_Country FindOne(Country_Query_Index country_Query_Index,object o)
    
  71.         {
    
  72.             using (var session = SessionManager.GetCurrentSession())
    
  73.             {
    
  74.                 Location_Country query = null;
    
  75. 
    
  76.                switch (country_Query_Index)
    
  77.                {
    
  78.                    case Country_Query_Index.CountryId:
    
  79.                        {
    
  80.                            query = session.QueryOver<Location_Country>()
    
  81.                                .Where(p => p.CountryId==(int)o)
    
  82.                                .SingleOrDefault();
    
  83.                            break;
    
  84.                        }
    
  85.                    case Country_Query_Index.CountryName:
    
  86.                        {
    
  87.                            query = session.QueryOver<Location_Country>()
    
  88.                                .Where(p => p.CountryName == o.ToString())
    
  89.                                .SingleOrDefault();
    
  90. 
    
  91.                            break;
    
  92.                        }
    
  93.                    case Country_Query_Index.Code1:
    
  94.                        {
    
  95.                            query = session.QueryOver<Location_Country>()
    
  96.                                .Where(p => p.CountryCode1 == o.ToString())
    
  97.                                .SingleOrDefault();
    
  98. 
    
  99.                            break;
    
  100.                        }
    
  101.                    case Country_Query_Index.Code2:
    
  102.                        {
    
  103.                            query = session.QueryOver<Location_Country>()
    
  104.                                .Where(p => p.CountryCode2 == o.ToString())
    
  105.                                .SingleOrDefault();
    
  106. 
    
  107.                            break;
    
  108.                        }
    
  109.                    case Country_Query_Index.DialCode:
    
  110.                        {
    
  111.                            query = session.QueryOver<Location_Country>()
    
  112.                                .Where(p => p.CountryDialCode == o.ToString())
    
  113.                                .SingleOrDefault();
    
  114. 
    
  115.                            break;
    
  116.                        }
    
  117.                }
    
  118. 
    
  119.                return query;
    
  120.            }
    
  121.         }
    
  122. 
    
  123.         public bool Create(Location_Country model)
    
  124.         {
    
  125.             bool result = false;
    
  126. 
    
  127.             using (var session = SessionManager.GetCurrentSession())
    
  128.             {
    
  129.                 using (var trans = session.BeginTransaction())
    
  130.                 {
    
  131. 
    
  132.                     session.Save(model);
    
  133.                     trans.Commit();
    
  134. 
    
  135.                     result = true;
    
  136.                 }
    
  137.             }
    
  138. 
    
  139.             return result;
    
  140.         }
    
  141. 
    
  142.         public bool Update(Location_Country model)
    
  143.         {
    
  144.             bool result = false;
    
  145. 
    
  146.             using (var session = SessionManager.GetCurrentSession())
    
  147.             {
    
  148.                 using (var trans = session.BeginTransaction())
    
  149.                 {
    
  150. 
    
  151.                     session.Update(model);
    
  152.                     trans.Commit();
    
  153. 
    
  154.                     result = true;
    
  155.                 }
    
  156.             }
    
  157. 
    
  158.             return result;
    
  159.         }
    
  160. 
    
  161.         public bool Delete(Location_Country model)
    
  162.         {
    
  163.             bool result = false;
    
  164. 
    
  165.             using (var session = SessionManager.GetCurrentSession())
    
  166.             {
    
  167.                 using (var trans = session.BeginTransaction())
    
  168.                 {
    
  169. 
    
  170.                     session.Delete(model);
    
  171.                     trans.Commit();
    
  172. 
    
  173.                     result = true;
    
  174.                 }
    
  175.             }
    
  176. 
    
  177.             return result;
    
  178.         }
    
  179.     }
    
posted @ 2011-10-29 20:35  Leo Wuang  阅读(3561)  评论(2编辑  收藏  举报