服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - 在C#项目中如何使用NHibernate详解

在C#项目中如何使用NHibernate详解

2022-02-22 13:32灵动生活 C#

NHibernate的设计思想和Hibernate的设计思想基本相同,都是为了避免频繁的编写sql脚本,使用面向对象的方式使用hql语句进行查询。下面这篇文章主要给大家介绍了关于在C#项目中如何使用NHibernate的相关资料,需要的朋友可以参考借鉴

前言

现代化大型项目通常使用独立的数据库来存储数据,其中以采用关系型数据库居多。用于开发项目的高级语言(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,位于数据访问层工具类库)

 在C#项目中如何使用NHibernate详解

 图1 添加对nhibernate的引用

3. 配置nhibernate

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
 <session-factory>
 <property name="connection.driver_class">nhibernate.driver.sqlclientdriver</property>
 <property name="connection.connection_string">
 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
 </property>
 <property name="adonet.batch_size">10</property>
 <property name="show_sql">true</property>
 <property name="dialect">nhibernate.dialect.mssql2005dialect</property>
 <property name="command_timeout">10</property>
 <property name="query.substitutions">true 1, false 0, yes 'y', no 'n'</property>
 <property name="proxyfactory.factory_class"> nhibernate.bytecode.spring.proxyfactoryfactory,nhibernate.bytecode.spring</property>
 <property name="connection.release_mode">on_close</property>
 <mapping assembly="fuli.entity"/>
 </session-factory>
</hibernate-configuration>

4. 编写nhibernatehelper辅助类

文件:nhibernatehelper.cs

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using system;
using fuli.tool.log;
using nhibernate;
using nhibernate.cfg;
namespace fuli.dal.common
{
 public class nhibernatehelper
 {
 private static isessionfactory _sessionfactory;
 private static isessionfactory sessionfactory
 {
  get
  {
  if (_sessionfactory == null)
  {
   var configuration = new configuration();
   configuration.configure();
   _sessionfactory = configuration.buildsessionfactory();
  }
  return _sessionfactory;
  }
 }
 
 public static isession opensession()
 {
  try
  {
  return sessionfactory.opensession();
  }
  catch (exception ex)
  {
  loghelper.getinstance().writemessage("打开数据库失败,错误:" + ex.tostring());
  return null;
  }
 }
 }
}

5. 创建数据模型

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
using system;
using system.collections.generic;
 
namespace fuli.entity.domain
{
 /// <summary>
 /// 共享编码表(字典表)
 /// </summary>
 [serializable]
 public class sharedcode
 {
 #region 构造方法
 
 public sharedcode()
 {
  m_id = 0;
  m_category = string.empty;
  m_text = string.empty;
  m_value = string.empty;
  m_isdefault = false;
  m_description = string.empty;
  m_parentid = 0;
  m_sortorder = 0;
 }
 
 #endregion 构造方法
 
 #region 私有变量
 
 private long m_id;
 private string m_category;
 private string m_text;
 private string m_value;
 private bool m_isdefault;
 private string m_description;
 private long m_parentid;
 private short m_sortorder;
 
 #endregion 私有变量
 
 #region 公有属性
 
 ///<summary>
 /// 主键id
 ///</summary>
 public virtual long id
 {
  get { return m_id; }
  set { m_id = value; }
 }
 
 ///<summary>
 /// 分类
 ///</summary>
 public virtual string category
 {
  get { return m_category; }
  set { m_category = value; }
 }
 
 ///<summary>
 /// 文本
 ///</summary>
 public virtual string text
 {
  get { return m_text; }
  set { m_text = value; }
 }
 
 ///<summary>
 /// 编码值
 ///</summary>
 public virtual string value
 {
  get { return m_value; }
  set { m_value = value; }
 }
 
 ///<summary>
 /// 是否是同类里默认
 ///</summary>
 public virtual bool isdefault
 {
  get { return m_isdefault; }
  set { m_isdefault = value; }
 }
 
 ///<summary>
 /// 描述
 ///</summary>
 public virtual string description
 {
  get { return m_description; }
  set { m_description = value; }
 }
 
 ///<summary>
 /// 父级id(如果有)
 ///</summary>
 public virtual long parentid
 {
  get { return m_parentid; }
  set { m_parentid = value; }
 }
 
 ///<summary>
 /// 排列次序
 ///</summary>
 public virtual short sortorder
 {
  get { return m_sortorder; }
  set { m_sortorder = value; }
 }
 
 #endregion 公有属性
 
 #region 扩展属性
 
 #endregion 扩展属性
 
 #region rewrite equals and hashcode
 
 /// <summary>
 ///
 /// </summary>
 public override bool equals(object obj)
 {
  if(this == obj) return true;
  if((obj == null) || (obj.gettype() != gettype())) return false;
  sharedcode castobj = (sharedcode)obj;
  return (castobj != null) && (m_id == castobj.id);
 }
 
 /// <summary>
 /// 用唯一值实现gethashcode
 /// </summary>
 public override int gethashcode()
 {
  int hash = 57;
  hash = 27 * hash * m_id.gethashcode();
  return hash;
 }
 
 #endregion rewrite equals and hashcode
 }
}

6. 创建nhibernate映射文件

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

文件:sharedcode.hbm.xml

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
 <class name="fuli.entity.domain.sharedcode, fuli.entity" table="sharedcode">
  <id name="id" column="id" type="int64" unsaved-value="0">
   <generator class="native"/>
  </id>
  <property name="category" type="string" column="category"/>
  <property name="text" type="string" column="text"/>
  <property name="value" type="string" column="value"/>
  <property name="isdefault" type="boolean" column="isdefault"/>
  <property name="description" type="string" column="description"/>
  <property name="parentid" type="int64" column="parentid"/>
  <property name="sortorder" type="int16" column="sortorder"/>
 </class>
</hibernate-mapping>

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

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

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

 在C#项目中如何使用NHibernate详解

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

7. 使用 nhibernate连接数据库

文件:commonrepository

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
namespace fuli.dal.sqlserverimpl
{
 public class commonrepository : icommonrepository
 {
  #region 新增
  /// <summary>
  /// 新增实体表
  /// </summary>
  /// <param name="obj"></param>
  /// <returns></returns>
  public long addnewentity<t>(object obj, string tablename) where t : new()
  {
   long id = 0;
   try
   {
    using (isession session = nhibernatehelper.opensession())
    {
     id = long.parse(session.save((t)obj).tostring());
     session.flush();
    }
   }
   catch (exception ex)
   {
    loghelper.getinstance().writemessage(tablename + operationtype.comma + ex.tostring());
   }
   return id;
  }
 
  /// <summary>
  /// 新增实体表
  /// </summary>
  /// <param name="entity"></param>
  /// <returns></returns>
  public treturn addnewentity<tentity, treturn>(object entity, string tablename) where tentity : new()
  {
   treturn returnvalue = default(treturn);
   try
   {
    using (isession session = nhibernatehelper.opensession())
    {
     object returnobject = session.save(entity);
     if (returnobject != null)
     {
      returnvalue = (treturn)convert.changetype(returnobject, typeof(treturn));
     }
     session.flush();
    }
   }
   catch (exception ex)
   {
    loghelper.getinstance().writemessage(tablename + operationtype.comma + ex.tostring());
   }
   return returnvalue;
  }
  #endregion 新增
 }
}

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

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。

原文链接:http://www.cnblogs.com/ywqu/p/8664360.html

延伸 · 阅读

精彩推荐
  • C#c#学习之30分钟学会XAML

    c#学习之30分钟学会XAML

    一个界面程序的核心,无疑就是界面和后台代码,而xaml就是微软为构建应用程序界面而创建的一种描述性语言,也就是说,这东西是搞界面的...

    C#教程网8812021-12-10
  • C#浅谈C# winForm 窗体闪烁的问题

    浅谈C# winForm 窗体闪烁的问题

    下面小编就为大家带来一篇浅谈C# winForm 窗体闪烁的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    C#教程网7962021-12-21
  • C#Unity3D UGUI实现缩放循环拖动卡牌展示效果

    Unity3D UGUI实现缩放循环拖动卡牌展示效果

    这篇文章主要为大家详细介绍了Unity3D UGUI实现缩放循环拖动展示卡牌效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参...

    诗远3662022-03-11
  • C#C#实现的文件操作封装类完整实例【删除,移动,复制,重命名】

    C#实现的文件操作封装类完整实例【删除,移动,复制,重命名】

    这篇文章主要介绍了C#实现的文件操作封装类,结合完整实例形式分析了C#封装文件的删除,移动,复制,重命名等操作相关实现技巧,需要的朋友可以参考下...

    Rising_Sun3892021-12-28
  • C#聊一聊C#接口问题 新手速来围观

    聊一聊C#接口问题 新手速来围观

    聊一聊C#接口问题,新手速来围观,一个通俗易懂的例子帮助大家更好的理解C#接口问题,感兴趣的小伙伴们可以参考一下...

    zenkey7072021-12-03
  • C#C# 后台处理图片的几种方法

    C# 后台处理图片的几种方法

    本篇文章主要介绍了C# 后台处理图片的几种方法,非常具有实用价值,需要的朋友可以参考下。...

    IT小伙儿10162021-12-08
  • C#C#基础之泛型

    C#基础之泛型

    泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个新功能。接下来通过本文给大家介绍c#基础之泛型,感兴趣的朋友一起学习吧...

    方小白7732021-12-03
  • C#C#直线的最小二乘法线性回归运算实例

    C#直线的最小二乘法线性回归运算实例

    这篇文章主要介绍了C#直线的最小二乘法线性回归运算方法,实例分析了给定一组点,用最小二乘法进行线性回归运算的实现技巧,具有一定参考借鉴价值,需要...

    北风其凉8912021-10-18