1、Nhibernate简介

NHibernate是一个面向.NET环境的对象/关系数据库映射工具。对象/关系数据库映射(object/relational mapping,ORM)这个术语表示一种技术,用来把对象模型表示的对象映射到基于SQL的关系模型数据结构中去

  简单的说就是将数据库的结构直接映射到实体模型之上,从而简化SQL的数据处理时间。通过XML(Fluent亦可)进行定义数据模型的持久化,nhibernate 内部的映射结构以及如图1-1所示:

2、准备

  • Nhibernate类库,下载直通车。压缩包内部所下载版本的源码,范例等。
  • 配置Visual Studio的NHibernate配置的智能提示,从上一部下载包中找到configuration.xsd和nhibernate-mapping.xsd放置X:\Program Files\Microsoft Visual Studio X\Xml\Schemas
  • Northwind数据库(范例数据库)也可以使其他的数据库
  • 建立NhibernateTest解决方案,目录结构如图1-2

3、使用范例

  NHibernate通过配置文件(app.config,web.config,db.cfg.xml)进行加载,从而得到ISessionFactory。一般而言,一个数据库保持一个ISessionFactory。ISessionFactory工厂进行创建ISession(Nhibernate工作单元)。ISession代表一次数据库的操作,一次操作之后需要对其进行关闭。

SessionFactory (NHibernate.ISessionFactory)
对属于单一数据库的编译过的映射文件的一个线程安全的,不可变的缓存快照。它是Session的工厂,是ConnectionProvider的客户。可以持有一个可选的(第二级)数据缓存,可以在进程级别或集群级别保存可以在事物中重用的数据。 会话,Session (NHibernate.ISession)
单线程,生命期短促的对象,代表应用程序和持久化层之间的一次对话。封装了一个ADO.NET连接。也是Transaction的工厂。保存有必需的(第一级)持久化对象的缓存,用于遍历对象图,或者通过标识符查找对象。  

  现在要实现针对Northwind数据库的Customers表进行读写数据

  • 配置Northwind.cfg.xml数据库的
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory name="nHibernate.Test">
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">
Server=.;initial catalog=Northwind;uid=sa;pwd=123456;Integrated Security=SSPI
</property>
<property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
<property name="show_sql">true</property>
<mapping assembly="nHibernateTest"/>
</session-factory>
</hibernate-configuration>
  • Customers实体对象映射,包含实体对象以及对应的映射xml

  这里有一点需要注意的:实体映射的id列是必须的,否则会报错。一般在配置文件中设置三种:native(根据底层数据库的能力选择 identity, sequence 或者 hilo中的一个),assigned(自己指定),forign(使用另外一个相关联的对象的标识符,和<one-to-one>联合一起使用。 )

 public class Customers:IAggregateRoot
{
public Customers()
{
}
public virtual string CustomerID { get; set; }
public virtual string CompanyName { get; set; }
public virtual string ContactName { get; set; }
public virtual string ContactTitle { get; set; }
public virtual string Address { get; set; }
public virtual string City { get; set; }
public virtual string Region { get; set; }
public virtual string PostalCode { get; set; }
public virtual string Country { get; set; }
public virtual string Phone { get; set; }
public virtual string Fax { get; set; }
}

  

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="nHibernateTest" namespace="nHibernateTest.Entity">
<class name="Customers" table="Customers">
<id name="CustomerID" column="CustomerID" type="String">
<generator class="assigned"/>
</id>
<property name="CompanyName" />
<property name="ContactName" />
<property name="ContactTitle" />
<property name="Address" />
<property name="City" />
<property name="Region" />
<property name="PostalCode" />
<property name="Country" />
<property name="Phone" />
<property name="Fax" />
</class>
</hibernate-mapping>
  • 控制台调用,实现对Customers的基本操作
      //数据库配置文件完全地址
var dbConfigFullPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Northwind.cfg.xml");
//Hibernate加载数据库配置文件
var nHConfiguration = new NHibernate.Cfg.Configuration().Configure("Northwind.cfg.xml");
//获得session工厂
var sessionFactory = nHConfiguration.BuildSessionFactory(); using (var session = sessionFactory.OpenSession())
{ var customer = new Customers()
{
CustomerID = "luge",
CompanyName = "卤鸽",
Address = "博客园",
Phone = "123456"
};
//插入数据
session.Save(customer);
session.Flush();
//get是直接执行sql语句得到实体对象
var getCustomer = session.Get<Customers>("luge"); getCustomer.CompanyName = "飞鸽";
session.SaveOrUpdate(getCustomer);
session.Flush();
//load主要在是需要调用的时候才进行执行sql语句
var loadCustomer = session.Load<Customers>("luge");
session.Delete(loadCustomer);
session.Flush();
}
  • 数据库表关系映射(一对多,多对多)

  Northwind数据库中①表Customers与表Orders是一对多关系②表Customers与表CustomerDemographics表示多对多关系。

  NHibernate针对集合进行映射的节点,(tip:由于笔者使用Nhibernate 4.0.3GA的最新版本,内部支持Net4.0的ISet<T>接口,并且已经去除了Iesi.Collections的引用)

<set>元素:它的元素存放没有顺序且不重复;

<list>元素:它需要在集合属性对应的数据库表中用一个额外的索引列保存每个元素的位置。

<bag>元素:它的元素可能重复,但不保存顺序

<map>元素:它的元素以键值对的形式保存,也是无序的,它的元素可以按自然顺序排序

  Customers与Orders之间xml配置如下:

<!--Customers xml mapping  -->
<set name="Orders" generate="true">
<key column="CustomerID" />
<one-to-many class="Orders"/>
</set>
//Customers实体增加
//构造函数
public Customers()
{
Orders=new HashSet<Orders>();
}
public virtual ISet<Orders> Orders{get;set;} <!--Orders xml mapping-->
<many-to-one name="Customers" class="Customers" >
<column name="CustomerID"/>
</many-to-one>
//Orders实体增加
public virtual Customers Customers{get;set;}
//多对多关系
<!--Customers xml mapping-->
<set name="CustomerDemographics" table="CustomerCustomerDemo" schema="dbo" generic="true">
<key column="CustomerID" />
<many-to-many class="CustomerDemographics" fetch="join" column="CustomerTypeID"/>
</set>
//Customers实体,构造函数相应增加实例化
public virtual ISet<CustomerDemographics> CustomerDemographics{get;set;} <!--CustomerDemographics xml mapping-->
<set name="Customers" table="CustomerCustomerDemo" >
<key column="CustomerTypeID"/>
<many-to-many class="Customers" fetch="join" column="CustomerID"/>
</set>
//CustomerDemographics实体增加实例化
public virtual ISet<Customers> Customers{get;set;}

4、扩展

  针对具体项目使用时,一般对NHibernate进行封装。笔者这里抽象一个IRepositoryd<T,TEntity> 接口作为公用接口(本文内容只是范例,如若用于具体项目自行调整)

public interface IRepository<T, EntityKey> where T : IAggregateRoot
{
void Add(T entity); void Remove(T entity); void Save(T entity); T FindBy(EntityKey Id); IEnumerable<T> FindAll(); IEnumerable<T> FindAll(int index, int pageSize, out int count); IEnumerable<T> FindBy(IList<ICriterion> queryList, Order order); IEnumerable<T> FindBy(IList<ICriterion> queryList,Order order, int index,int pageSize,out int count);
}
public abstract class Repository<T, EntityKey> : IRepository<T, EntityKey>
where T : IAggregateRoot
{
private IUnitOfWork _uow; public Repository(IUnitOfWork uow)
{
_uow = uow;
} public void Add(T entity)
{
_uow.RegisterNew(entity);
//throw new NotImplementedException();
} public void Remove(T entity)
{
_uow.RegisterRemoved(entity);
//throw new NotImplementedException();
} public void Save(T entity)
{
_uow.RegisterAmended(entity);
} public T FindBy(EntityKey Id)
{
return _uow.Session.Get<T>(Id);
} public IEnumerable<T> FindAll()
{
return (List<T>)_uow.Session.CreateCriteria(typeof(T)).List();
} public IEnumerable<T> FindAll(int index, int pageSize, out int count)
{
ICriteria CriteriaQuery = _uow.Session.CreateCriteria(typeof(T)); index=(index>=?index:); var countCirteria = CriteriaQuery.Clone() as ICriteria; var futureCount = countCirteria.SetProjection(Projections.RowCount()).FutureValue<Int32>(); count = futureCount.Value; var queryList = CriteriaQuery.SetFirstResult((index-)*pageSize).SetMaxResults(pageSize).List(); return (List<T>)queryList;
} public IEnumerable<T> FindBy(IList<ICriterion> queryList, Order order)
{
//Restrictions.Eq("Category.Id", 2) 进行添加查询数据
ICriteria CriteriaQuery = _uow.Session.CreateCriteria(typeof(T)); foreach (var queryItem in queryList)
{
CriteriaQuery.Add(queryItem);
} return CriteriaQuery.AddOrder(order).List<T>();
} /// <summary>
///
/// </summary>
/// <param name="queryList"></param>
/// <param name="order"></param>
/// <param name="index"></param>
/// <param name="count"></param>
/// <returns></returns>
public IEnumerable<T> FindBy(IList<ICriterion> queryList, Order order, int index, int pageSize, out int count)
{ ICriteria CriteriaQuery = _uow.Session.CreateCriteria(typeof(T)); foreach (var queryItem in queryList)
{
CriteriaQuery.Add(queryItem);
} var listByQuery = CriteriaQuery; var countCrieriaQuery = CriteriaQuery.Clone() as ICriteria; var rowCount = countCrieriaQuery.SetProjection(Projections.RowCount()).FutureValue<Int32>(); count = rowCount.Value; index = index >= ? index : ; return listByQuery.AddOrder(order).SetFirstResult((index - ) * pageSize).SetMaxResults(pageSize).List<T>();
}

5、本文例子的源码下载

源码(如果觉得不错请点赞下,有误的话请指出,卤鸽在此感谢)

参考:

http://www.cnblogs.com/lyj/archive/2008/10/30/1323099.html

ASP.NET 设计模式

Nhibernate基础使用教程以及简易封装的更多相关文章

  1. python基础系列教程——Python3.x标准模块库目录

    python基础系列教程——Python3.x标准模块库目录 文本 string:通用字符串操作 re:正则表达式操作 difflib:差异计算工具 textwrap:文本填充 unicodedata ...

  2. Android基础新手教程——3.7 AnsyncTask异步任务

    Android基础新手教程--3.7 AnsyncTask异步任务 标签(空格分隔): Android基础新手教程 本节引言: 本节给大家带来的是Android给我们提供的一个轻量级的用于处理异步任务 ...

  3. Android基础新手教程——3.4 TouchListener PK OnTouchEvent + 多点触碰

    Android基础新手教程--3.4 TouchListener PK OnTouchEvent + 多点触碰 标签(空格分隔): Android基础新手教程 本节引言: 如题,本节给大家带来的是To ...

  4. Android基础新手教程——1.2.1 使用Eclipse + ADT + SDK开发Android APP

    Android基础新手教程--1.2.1 使用Eclipse + ADT + SDK开发Android APP 标签(空格分隔): Android基础新手教程 1.前言 这里我们有两条路能够选,直接使 ...

  5. Android基础新手教程——3.8 Gestures(手势)

    Android基础新手教程--3.8 Gesture(手势) 标签(空格分隔): Android基础新手教程 本节引言: 周六不歇息,刚剪完了个大平头回来.继续码字~ 好的,本节给大家带来点的是第三章 ...

  6. ECMAScript 6.0基础入门教程

    ECMAScript 6.0基础入门教程 转:https://blog.csdn.net/hexinyu_1022/article/details/80778727 https://blog.csdn ...

  7. 面localStorage用作数据缓存的简易封装

    面localStorage用作数据缓存的简易封装 最近做了一些前端控件的封装,需要用到数据本地存储,开始采用cookie,发现很容易就超过了cookie的容量限制,于是改用localStorage,但 ...

  8. Nhibernate 4.0 教程入门

    Nhibernate 4.0 教程 目录 1.      下载Nhibernate 4.04. 1 2.      入门教程... 2 3.      测试项目详解... 3 4.      总结.. ...

  9. [.net 面向对象编程基础] (11) 面向对象三大特性——封装

    [.net 面向对象编程基础] (11) 面向对象三大特性——封装 我们的课题是面向对象编程,前面主要介绍了面向对象的基础知识,而从这里开始才是面向对象的核心部分,即 面向对象的三大特性:封装.继承. ...

随机推荐

  1. 《深入理解Nginx》阅读与实践(三):使用upstream和subrequest访问第三方服务

    本文是对陶辉<深入理解Nginx>第5章内容的梳理以及实现,代码和注释基本出自此书. 一.upstream:以向nginx服务器的请求转化为向google服务器的搜索请求为例 (一)模块框 ...

  2. 循序渐进之Spring AOP(5) - 创建切面

    在掌握了可用的增强后,接下来要做的就是精确的描述切点.前面的示例都是指定一个目标类并把增强织入到所有方法中,实际开发显然会有更精细的筛选需求,比如对所有类中名称以test结尾的方法加入监控执行时间,或 ...

  3. 【DIOCP知识库】连接上下文TIocpClientContext

    来自弦子介绍 [概述] 该类管理远程连接,每一个远程连接会对应一个该类的实例,开发时可以通过继承该类,扩展属性,可以存储更多的连接信息,可以重写OnRecvBuffer方法进行数据逻辑的处理 [字段/ ...

  4. java多线程学习-开篇

    1.Java线程基本概念 在操作系统中两个比较容易混淆的概念是进程(process)和线程(thread).操作系统中的进程是资源的组织单位.进程有一个包含了程序内容和数据的地址空间,以及其它的资源, ...

  5. static关键字用法

    java中static关键字可用于修饰: 1.属性:表示该属性变量在类被加载时即被创建并初始化,类加载过程只进行一次,因此静态变量也只被创建一次 2.方法:静态方法为类的公有方法,可直接用‘类名.方法 ...

  6. markdown编辑器实现笔记

    1.js代码放在head和body的区别 <html> <head> <script src="https://cdnjs.cloudflare.com/aja ...

  7. var关键字详解

    1,var只能定义局部变量,而不能定义成员变量 2,定义的时候必须同时完成初始化,而不能使用var定义变量为null 3,var本身不是一个新类型,只是用来修饰一个可以推断出具体类型的局部变量 var ...

  8. python 高阶函数与装饰器

    高阶函数定义1.函数接收的参数是一个函数名2.函数的返回值是一个函数名以上两者满足任意一个,就是高阶函数装饰器定义本质就是函数,功能是为其他函数添加新功能 装饰器的原则 1.不修改被装饰函数的源代码( ...

  9. lsslot

    lsslot 命令 用途 显示动态可重新配置的插槽(比如热插拔)及其特性. 语法 lsslot -c ConnectorType [ -a | -o | -l DeviceName | -s Slot ...

  10. DOM、JDOM、DOM4J的区别(转载)

    DOM.JDOM.DOM4J的区别 分类: XML2012-06-11 20:47 5576人阅读 评论(6) 收藏 举报 文档xmlcollectionsjavaapi工作 dom是解析xml的底层 ...