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

<?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

 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自动代码工具从数据表生成数据模型和对应的映射文件。

 using System;
using System.Collections.Generic; namespace Fuli.Entity.Domain
{
/// <summary>
/// 共享编码表(字典表)
/// </summary>
[Serializable]
public class SharedCode
{
#region 构造方法 public SharedCode()
{
m_Id = ;
m_Category = string.Empty;
m_Text = string.Empty;
m_Value = string.Empty;
m_IsDefault = false;
m_Description = string.Empty;
m_ParentId = ;
m_SortOrder = ;
} #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 = ;
hash = * hash * m_Id.GetHashCode();
return hash;
} #endregion Rewrite Equals and HashCode
}
}

6. 创建NHibernate映射文件

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

文件:SharedCode.hbm.xml

<?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文件,那么映射就不会生效了。

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

7. 使用 NHibernate连接数据库

文件:CommonRepository

 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 = ;
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,专注负责相对应的实体操作。

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/

酷客多小程序  陈苏洲

如何在C#项目中使用NHibernate的更多相关文章

  1. [Laravel-Swagger]如何在 Laravel 项目中使用 Swagger

    如何在 Laravel 项目中使用 Swagger http://swagger.io/getting-started/ 安装依赖 swagger-php composer require zirco ...

  2. 如何在cocos2d项目中enable ARC

    如何在cocos2d项目中enable ARC 基本思想就是不支持ARC的代码用和支持ARC的分开,通过xcode中设置编译选项,让支持和不支持ARC的代码共存. cocos2d是ios app开发中 ...

  3. 如何在NodeJS项目中优雅的使用ES6

    如何在NodeJS项目中优雅的使用ES6 NodeJs最近的版本都开始支持ES6(ES2015)的新特性了,设置已经支持了async/await这样的更高级的特性.只是在使用的时候需要在node后面加 ...

  4. 如何在VUE项目中添加ESLint

    如何在VUE项目中添加ESLint 1. 首先在项目的根目录下 新建 .eslintrc.js文件,其配置规则可以如下:(自己小整理了一份),所有的代码如下: // https://eslint.or ...

  5. 如何在mvc项目中使用apiController

    文章地址:How do you route from an MVC project to an MVC ApiController in another project? 文章地址:How to Us ...

  6. 如何在Ionic2项目中使用第三方JavaScript库

    onic的官网放出一记大招Ionic and Typings,来介绍如何在Ionic2项目中使用第三方JavaScript库. 因为在前阵子正好想用一个非常有名的第三方JS库ChartJs来实现一些东 ...

  7. 如何在maven项目中使用spring

    今天开始在maven项目下加入spring. 边学习边截图. 在这个过程中我新建了一个hellospring的项目.于是乎从这个项目出发开始研究如何在maven项目中使用spring.鉴于网上的学习资 ...

  8. 如何在Vue-cli项目中使用JTopo

    1.前言 jTopo(Javascript Topology library)是一款完全基于HTML5 Canvas的关系.拓扑图形化界面开发工具包.其体积小,性能优异,由一群开发爱好者来维护.唯一感 ...

  9. 如何在Vue项目中给路由跳转加上进度条

    1.前言 在平常浏览网页时,我们会注意到在有的网站中,当点击页面中的链接进行路由跳转时,页面顶部会有一个进度条,用来标示页面跳转的进度(如下图所示).虽然实际用处不大,但是对用户来说,有个进度条会大大 ...

随机推荐

  1. 如何利用Plxmon工具进行在线烧录PCI卡的EEPROM

    PLXMON是PLX公司提供的用于在线烧录PCI卡的EEPROM的工具. 烧录EEPROM有两种方式,一是比较传统的方法,即采用烧录机进行烧录.采用这种方式时,在调试过程中EEPROM需采用插件式封装 ...

  2. 给vmware的Linux虚拟机添加硬盘

    给vmware的Linux虚拟机添加硬盘   1.先将虚拟机Power Off,在Virtual Machine Setting对话框里点击左下角的"Add",选择"Ha ...

  3. Java中的switch语句后面的控制表达式的数据类型

    Java中的switch语句后面的控制表达式的数据类型 1.byte 2.char 3.short 4.int 5.枚举类型 6.Java 7允许java.lang.String类型

  4. HTML5可以省略全部标记的元素

    HTML5可以省略全部标记的元素 1.body 2.colgroup 3.html 4.head 5.tbody

  5. 手机端仿ios的省市县3级联动脚本一

    一,图片实例 二,代码 2.1,代码 $('#provinceCity_fu').click(function(){ var $this = $(this); new Picker({ "t ...

  6. Struts2的数据封装

    在很多的实际开发场景中,页面提交请求参数Action ,在Action中接收参数并对接收的数据进行封装.封装到一个JavaBean中,将JavaBean传递给业务层中.Struts2数据封装分为两类: ...

  7. 学习一之UML类图

    前言 最近在学习程杰老师的<大话设计模式>,觉得非常不错,就做了一些学习笔记和总结.如果对设计模式很感兴趣的,可以直接阅读书籍,相信会有更多的收获. 本人小菜一枚,如果理解的不对的还请多多 ...

  8. 浏览器全屏之requestFullScreen全屏与F11全屏

    一.简介 浏览器全屏有两种方式,一种是HTML5新增的requestFullscree全屏,另一种是摁F11实现的全屏,本文将详解两种全屏的特点以及实现代码. 二.requestFullscreen全 ...

  9. Keras官方中文文档:Keras安装和配置指南(Linux)

    关于计算机的硬件配置说明 推荐配置 如果您是高校学生或者高级研究人员,并且实验室或者个人资金充沛,建议您采用如下配置: 主板:X299型号或Z270型号 CPU: i7-6950X或i7-7700K ...

  10. [LOJ2230][BJOI2014]大融合

    题面戳我 sol LCT维护子树size. 开一个数组\(sz_i\)表示一个节点的所有虚儿子的size和,\(sum_i\)表示以一个节点为根的子树的\(size\)和,可见\(sz_u=\sum_ ...