经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » ASP.net » 查看文章
如何在C#项目中使用NHibernate
来源:cnblogs  作者:灵动生活  时间:2018/9/25 20:43:02  对本文有异议

现代化大型项目通常使用独立的数据库来存储数据,其中以采用关系型数据库居多。用于开发项目的高级语言(C#、Java等)是面向对象的,而关系型数据库是基于关系的,两者之间的沟通需要一种转换,也就是对象/关系数据库映射(Object/Relational Mapping,简称ORM)。

C#可用以解决对象/关系数据库映射的工具有多种,常见的有EF (Entity Framework)、NHibernate、iBATIS等,各自的优缺点及适用场景在此不做讨论,本文只对如何使用NHibernate做个总结。

NHibernate是一个面向.NET环境的对象/关系数据库映射工具。

1. 创建项目文件

在Visual Studio开发工具里创建需要的项目结构。

2. 添加对NHibernate的引用

当下载并解压NHibernate安装包后,电脑上就会创建一些目录,包括“Required_Bins”,要把 Required_Bins目录下的DLL引用到项目里来,它们是NHibernate使用的核心组件。

NHibernate.dll(基础类库,与数据库直接打交道,位于数据访问层)

Iesi.Collections(基础类库辅助类库,位于数据访问层)

Antlr3.Runtime(基础类库辅助类库,位于数据访问层)

NHibernate.ByteCode.Spring.dll(Proxy Factory类库,用于打开/关闭Nhibernate Session,位于数据访问层工具类库)

 

                                       图1 添加对NHibernate的引用

3. 配置NHibernate

文件:hibernate.cfg.xml,位于站点根目录

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
  3. <session-factory>
  4. <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
  5. <property name="connection.connection_string">
  6. Data Source=120.120.200.200;Initial Catalog=MAMall;Persist Security Info=True;User ID=mamall;Password=mima123;connection reset=false;connection lifetime=50;min pool size=1;max pool size=500
  7. </property>
  8. <property name="adonet.batch_size">10</property>
  9. <property name="show_sql">true</property>
  10. <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
  11. <property name="command_timeout">10</property>
  12. <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
  13. <property name="proxyfactory.factory_class"> NHibernate.ByteCode.Spring.ProxyFactoryFactory,NHibernate.ByteCode.Spring</property>
  14. <property name="connection.release_mode">on_close</property>
  15. <mapping assembly="Fuli.Entity"/>
  16. </session-factory>
  17. </hibernate-configuration>

4. 编写NHibernateHelper辅助类

文件:NHibernateHelper.cs

  1. 1 using System;
  2. 2 using Fuli.Tool.Log;
  3. 3 using NHibernate;
  4. 4 using NHibernate.Cfg;
  5. 5
  6. 6 namespace Fuli.DAL.Common
  7. 7 {
  8. 8 public class NHibernateHelper
  9. 9 {
  10. 10 private static ISessionFactory _sessionFactory;
  11. 11 private static ISessionFactory SessionFactory
  12. 12 {
  13. 13 get
  14. 14 {
  15. 15 if (_sessionFactory == null)
  16. 16 {
  17. 17 var configuration = new Configuration();
  18. 18 configuration.Configure();
  19. 19 _sessionFactory = configuration.BuildSessionFactory();
  20. 20 }
  21. 21 return _sessionFactory;
  22. 22 }
  23. 23 }
  24. 24
  25. 25 public static ISession OpenSession()
  26. 26 {
  27. 27 try
  28. 28 {
  29. 29 return SessionFactory.OpenSession();
  30. 30 }
  31. 31 catch (Exception ex)
  32. 32 {
  33. 33 LogHelper.GetInstance().WriteMessage("打开数据库失败,错误:" + ex.ToString());
  34. 34 return null;
  35. 35 }
  36. 36 }
  37. 37 }
  38. 38 }

5. 创建数据模型

NHibernate允许直接使用Plain Old CLR Objects (POCOs),而不用通过存储过程来直接和数据库交互。使用POCOs的一个优势在于不用绑定特定的持久化层。相比较而言,有些ORM解决方案需要特殊属性,或者是基于模型对象,这些对象又是从特定的基类中继承而来的。

在NHibernate中不用特殊的修饰就可以让对象和持久化层交互。要注意的是所有需要持久化的属性必须是虚拟的,并且要开启延迟加载,所有数据模型类中的公共方法必须是虚拟的,哪怕它们并没有包含到映射文件中。

通常来讲,最好把所有的属性都设置为虚拟的。

可以借助MyGeneration自动代码工具从数据表生成数据模型和对应的映射文件。

  1. 1 using System;
  2. 2 using System.Collections.Generic;
  3. 3
  4. 4 namespace Fuli.Entity.Domain
  5. 5 {
  6. 6 /// <summary>
  7. 7 /// 共享编码表(字典表)
  8. 8 /// </summary>
  9. 9 [Serializable]
  10. 10 public class SharedCode
  11. 11 {
  12. 12 #region 构造方法
  13. 13
  14. 14 public SharedCode()
  15. 15 {
  16. 16 m_Id = 0;
  17. 17 m_Category = string.Empty;
  18. 18 m_Text = string.Empty;
  19. 19 m_Value = string.Empty;
  20. 20 m_IsDefault = false;
  21. 21 m_Description = string.Empty;
  22. 22 m_ParentId = 0;
  23. 23 m_SortOrder = 0;
  24. 24 }
  25. 25
  26. 26 #endregion 构造方法
  27. 27
  28. 28 #region 私有变量
  29. 29
  30. 30 private long m_Id;
  31. 31 private string m_Category;
  32. 32 private string m_Text;
  33. 33 private string m_Value;
  34. 34 private bool m_IsDefault;
  35. 35 private string m_Description;
  36. 36 private long m_ParentId;
  37. 37 private short m_SortOrder;
  38. 38
  39. 39 #endregion 私有变量
  40. 40
  41. 41 #region 公有属性
  42. 42
  43. 43 ///<summary>
  44. 44 /// 主键Id
  45. 45 ///</summary>
  46. 46 public virtual long Id
  47. 47 {
  48. 48 get { return m_Id; }
  49. 49 set { m_Id = value; }
  50. 50 }
  51. 51
  52. 52 ///<summary>
  53. 53 /// 分类
  54. 54 ///</summary>
  55. 55 public virtual string Category
  56. 56 {
  57. 57 get { return m_Category; }
  58. 58 set { m_Category = value; }
  59. 59 }
  60. 60
  61. 61 ///<summary>
  62. 62 /// 文本
  63. 63 ///</summary>
  64. 64 public virtual string Text
  65. 65 {
  66. 66 get { return m_Text; }
  67. 67 set { m_Text = value; }
  68. 68 }
  69. 69
  70. 70 ///<summary>
  71. 71 /// 编码值
  72. 72 ///</summary>
  73. 73 public virtual string Value
  74. 74 {
  75. 75 get { return m_Value; }
  76. 76 set { m_Value = value; }
  77. 77 }
  78. 78
  79. 79 ///<summary>
  80. 80 /// 是否是同类里默认
  81. 81 ///</summary>
  82. 82 public virtual bool IsDefault
  83. 83 {
  84. 84 get { return m_IsDefault; }
  85. 85 set { m_IsDefault = value; }
  86. 86 }
  87. 87
  88. 88 ///<summary>
  89. 89 /// 描述
  90. 90 ///</summary>
  91. 91 public virtual string Description
  92. 92 {
  93. 93 get { return m_Description; }
  94. 94 set { m_Description = value; }
  95. 95 }
  96. 96
  97. 97 ///<summary>
  98. 98 /// 父级Id(如果有)
  99. 99 ///</summary>
  100. 100 public virtual long ParentId
  101. 101 {
  102. 102 get { return m_ParentId; }
  103. 103 set { m_ParentId = value; }
  104. 104 }
  105. 105
  106. 106 ///<summary>
  107. 107 /// 排列次序
  108. 108 ///</summary>
  109. 109 public virtual short SortOrder
  110. 110 {
  111. 111 get { return m_SortOrder; }
  112. 112 set { m_SortOrder = value; }
  113. 113 }
  114. 114
  115. 115 #endregion 公有属性
  116. 116
  117. 117 #region 扩展属性
  118. 118
  119. 119 #endregion 扩展属性
  120. 120
  121. 121 #region Rewrite Equals and HashCode
  122. 122
  123. 123 /// <summary>
  124. 124 ///
  125. 125 /// </summary>
  126. 126 public override bool Equals(object obj)
  127. 127 {
  128. 128 if(this == obj) return true;
  129. 129 if((obj == null) || (obj.GetType() != GetType())) return false;
  130. 130 SharedCode castObj = (SharedCode)obj;
  131. 131 return (castObj != null) && (m_Id == castObj.Id);
  132. 132 }
  133. 133
  134. 134 /// <summary>
  135. 135 /// 用唯一值实现GetHashCode
  136. 136 /// </summary>
  137. 137 public override int GetHashCode()
  138. 138 {
  139. 139 int hash = 57;
  140. 140 hash = 27 * hash * m_Id.GetHashCode();
  141. 141 return hash;
  142. 142 }
  143. 143
  144. 144 #endregion Rewrite Equals and HashCode
  145. 145 }
  146. 146 }

6. 创建NHibernate映射文件

Nhibernate使用XML映射文件来映射POCO到数据库对象。虽然在很多案例中这可能是一对一关系,但这并不是必定的。

文件:SharedCode.hbm.xml

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  3. <class name="Fuli.Entity.Domain.SharedCode, Fuli.Entity" table="SharedCode">
  4. <id name="Id" column="Id" type="Int64" unsaved-value="0">
  5. <generator class="native"/>
  6. </id>
  7. <property name="Category" type="String" column="Category"/>
  8. <property name="Text" type="String" column="Text"/>
  9. <property name="Value" type="String" column="Value"/>
  10. <property name="IsDefault" type="Boolean" column="IsDefault"/>
  11. <property name="Description" type="String" column="Description"/>
  12. <property name="ParentId" type="Int64" column="ParentId"/>
  13. <property name="SortOrder" type="Int16" column="SortOrder"/>
  14. </class>
  15. </hibernate-mapping>

在hibernate-maping标签中,同时引用类集(POCOs)所属的程序集命名空间。

  • class元素表示到单个POCO的映射。name表示上面的程序集和命名空间中的类名,table属性告诉NHibernate数据库中的哪个表或者视图将被映射。
  • id元素告诉NHibernate哪个数据库的字段和对应的对象作为一个唯一键来使用。在本例中,我们使用Id这个字段。
  • generator元素告诉NHibernate怎样给新实体来创建唯一ID。
  • property标签是见得最多的标签。它简单地映射一个到数据表或者视图中对应字段的映射。

一旦XML文件创建好了,需要更改XML的生成方式确保它被设置为嵌入式资源,否则NHibernate不会读取这个XML文件,那么映射就不会生效了。

 

          图2 映射文件必须是嵌入的资源

7. 使用 NHibernate连接数据库

文件:CommonRepository

  1. 1 namespace Fuli.DAL.SQLServerImpl
  2. 2 {
  3. 3 public class CommonRepository : ICommonRepository
  4. 4 {
  5. 5 #region 新增
  6. 6
  7. 7 /// <summary>
  8. 8 /// 新增实体表
  9. 9 /// </summary>
  10. 10 /// <param name="obj"></param>
  11. 11 /// <returns></returns>
  12. 12 public long AddNewEntity<T>(object obj, string tableName) where T : new()
  13. 13 {
  14. 14 long id = 0;
  15. 15 try
  16. 16 {
  17. 17 using (ISession session = NHibernateHelper.OpenSession())
  18. 18 {
  19. 19 id = long.Parse(session.Save((T)obj).ToString());
  20. 20 session.Flush();
  21. 21 }
  22. 22 }
  23. 23 catch (Exception ex)
  24. 24 {
  25. 25 LogHelper.GetInstance().WriteMessage(tableName + OperationType.COMMA + ex.ToString());
  26. 26 }
  27. 27 return id;
  28. 28 }
  29. 29
  30. 30 /// <summary>
  31. 31 /// 新增实体表
  32. 32 /// </summary>
  33. 33 /// <param name="entity"></param>
  34. 34 /// <returns></returns>
  35. 35 public TReturn AddNewEntity<TEntity, TReturn>(object entity, string tableName) where TEntity : new()
  36. 36 {
  37. 37 TReturn returnValue = default(TReturn);
  38. 38 try
  39. 39 {
  40. 40 using (ISession session = NHibernateHelper.OpenSession())
  41. 41 {
  42. 42 object returnObject = session.Save(entity);
  43. 43 if (returnObject != null)
  44. 44 {
  45. 45 returnValue = (TReturn)Convert.ChangeType(returnObject, typeof(TReturn));
  46. 46 }
  47. 47 session.Flush();
  48. 48 }
  49. 49 }
  50. 50 catch (Exception ex)
  51. 51 {
  52. 52 LogHelper.GetInstance().WriteMessage(tableName + OperationType.COMMA + ex.ToString());
  53. 53 }
  54. 54
  55. 55 return returnValue;
  56. 56 }
  57. 57
  58. 58 #endregion 新增
  59. 59 }
  60. 60 }

对于不同的实体,可以一对一地写一个<Entity>Repository,专注负责相对应的实体操作。

8. 附录

NHibernate开源项目:https://sourceforge.net/projects/nhibernate/files/NHibernate/

Your first NHibernate based application:http://nhibernate.info/doc/tutorials/first-nh-app/your-first-nhibernate-based-application.html

NHibernate 快速上手:http://www.oschina.net/translate/nhibernate-quickstart?p=1#comments

Quickstart with NHibernate:https://docs.google.com/document/d/1OTC16N1GnKvgkIDvQn_RkQS_y3vvjYav-Ons9JLEUCU/edit?pli=1

NHibernate词条:https://baike.baidu.com/item/NHibernate

ANTLR:http://www.antlr.org/

 

酷客多小程序  陈苏

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号