首先,非常感谢提出问题的朋友们,使得本人又去深入研究了NHibernate的《Session-Per-Request 模式》。

  前言:

谈到NHibernate大伙并不陌生,搞Java的更是清楚,Hibernate是一个目前应用的最广泛的开放源代码的对象关系映射框架,它对Java的JDBC(类似于ADO.Net)进行了非常轻量级的对象封装。NHibernate 是一个基于.Net 的针对关系型数据库的对象持久化类库。Nhibernate 来源于非常优秀的基于Java的Hibernate 关系型持久化工具(ORM)。

体系结构

SessionFactory(NHibernate.IsessionFactory):它是Session的工厂,是ConnectionProvider的客户。可以持有一个可选的(第二级)数据缓存,可以在进程级别或集群级别保存的可以在事物中重用的数据。

会话(NHibernate.ISession):线程,生命期较短的对象,代表应用程序和持久化层之间的一次对话。封装了一个ADO.NET连接,也是Transaction的工厂。保存有必需的(第一级)持久化对象的缓存,用于遍历对象图,或者通过标识符查找对象。

持久化对象(Persistent)其集合(Collections):生命期较短的单线程的对象,包含了持久化状态和商业功能。这些可能是普通的对象,唯一特别的是现在从属于且仅从属于一个Session。一旦Session被关闭,它们都将从Session中取消联系,可以在任何程序层自由使用(比如,直接作为传送到表现层的DTO,数据传输对象)。

事务Transaction (NHibernate.ITransaction):(可选)单线程,生命期较短的对象,应用程序用其来表示一批工作的原子操作,它是底层的ADO.NET事务的抽象。一个Session在某些情况下可能跨越多个Transaction事务。

持久化类

持久化类是暂时存在的,实例会被持久性保存于数据库中.如:virtual public string Name { get; set; }

NHibernate默认使用代理功能,要求持久化类不是sealed的,而且其公共方法、属性和事件声明为virtual。

属性不一定需要声明为public的。NHibernate可以对default、protected、internal或private的属性执行持久化.

映射(Mapping)

对象和关系数据库之间的映射是用一个XML文档(XML document)来定义的。

 使用方法(结合MVC3开发)

  1. 添加Nugget包:如下图:

                         

            

                                                

2、在项目中配置NHibernate:

(1)、打开本项目文件夹下有个"packages"文件夹-->NHibernate.3.3.3.4000-->ConfigurationTemplates-->MSSQL.cfg.xml。

(2)、复制MSSQL.cfg.xml到项目根目录下,改名为”hibernate.cfg.xml“,紧接着 右键属性:无,如果较新则复制。否则出现“failed: NHibernate.Cfg.HibernateConfigException : An exception occurred during configuration of persistence layer. ----> System.IO.FileNotFoundException : 未能找到文件“NHibernateSample\NHibernateSample.Data.Test\bin\Debug\hibernate.cfg.xml””异常

如下图:

3、数据库中添加表:Users。

4、在项目中建立”Entities“文件夹,添加Users类。

logs_code_hide('753e65b7-2e06-48af-924c-a40e21886c5f',event)" src="/Upload/Images/2013082110/2B1B950FA3DF188F.gif" alt="" />

  public class Users
{
virtual public int ID { get; set; }
[DisplayName("姓名")]
virtual public string Name { get; set; }
[DisplayName("密码")]
virtual public string PassWord { get; set; }
[DisplayName("身高")]
virtual public string Height { get; set; }
[DisplayName("工作")]
virtual public string Descript { get; set;
[DisplayName("创建时间")]
virtual public DateTime CreateTime { get; set; }
}

Users类

5、添加”Users.hbm.xml“,右键属性:不复制,嵌入的资源。

6、XML出现智能提示,在代码中右键属性:架构添加:nhibernate-configuration.xsd和nhibernate-mapping.xsd,文件位置如下图:

7、Users.hbm.xml文档代码如下:

(1) <hibernate-mappingxmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateDemo" namespace="NHibernateDemo.Entities">

解释:定义了NHibernate的版本信息,assembly:加载的程序集名称。namespace:映射到体类的文件夹。

(2) <class name="Users"  table="Users" lazy="false">,name定义了所要映射的类,table定义了要映射的数据库中的表,lazy定义了是否要延迟加载,如    果是默认值的话lazy=”true”,是延迟加载,这样的话需要在定义的类字段中加入Virtual,而lazy=”true”则不用延迟加载,立即执行。

(3)<id name="ID" column="ID"><generator class="native"/></id>

这段代码的作用是被映射的类必须定义对应数据库的表主键字段,属于int自增的。name标识实体属性的名字,column标识数据库主键的名字。

(4)<property name="Name"/>字段名称,如果实体类中的名称和数据库中的一致,不需要定义column。

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernateDemo"
namespace="NHibernateDemo.Entities">
<class name="Users" table="Users" >
<id name="ID" column="ID">
<generator class="native"/>
</id>
<property name="Name"/>
<property name="PassWord" />
<property name="Height"/>
<property name="Descript"/>
<property name="CreateTime"/>
</class>
</hibernate-mapping>

Users.hbm.xml

8、hibernate.cfg.xml文档代码如下:

(1) hibernate.dialect  数据库方言类,NHibernate根据不同的方言来适应不同的数据库,到0.7版只提供了支持MsSql2000的方言。

(2) hibernate.connection.driver_class  数据库连接的驱动类

(3) hibernate.connection.connection_string  数据库的连接字符串,包括主机名,数据库名,用户名和密码,注意,很多实际项目中出于安全性,会将该连接字符串写入注册表中,那么该参数就只能在程序中动态赋值了。

(4)将 current_session_context_class 配置为 web,NHibernate 在初始化时会生成 NHibernate.Context.WebSessionContext 类的实例

<hibernate-configuration  xmlns="urn:nhibernate-configuration-2.2" >
<session-factory name="NHibernate.Test">
<property name="current_session_context_class">web</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">
Server=.;initial catalog=TXUsers;User ID=sa;Password=sasa;Integrated Security=SSPI
</property>
<property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
<mapping assembly="NHibernateDemo"/>
</session-factory>
</hibernate-configuration>

hibernate.cfg.xml

创建NHibernateHelp类:

     (1)、我们要从ISessionFactory中获取一个ISession(NHibernate的工作单元)。

(2)、ISessionFactory可以创建并打开新的Session。

(3)、一个Session代表一个单线程的单元操作。 ISessionFactory是线程安全的,很多线程可以同时访问它。

(4)、ISession不是线程安全的,它代表与数据库之间的一次操作。ISession通过ISessionFactory打开,在所有的工作完成后,需要关闭。

(5)、ISessionFactory通常是个线程安全的全局对象,只需要被实例化一次。我们可以使用单例(Singleton)模式在程序中创建ISessionFactory。

(6)、有了返回的ISession类型的GetSession()方法,就可以实现增删改查的功能了。

(7)、看了一篇 Session-Per-Request 模式,归纳总结如下:(也同时感谢指出问题的朋友们

(8)、WebSessionContext 实现了 Session-Per-Request 模式,它封装了 HttpContext ,因此我们不需要在我们的辅助类(NHibernateSessionFactory 或是 NHibernateHelper)中再对 HttpContext 进行操作。

       (9)、我们只需要从 WebSessionContext 的实例中获取 Session 即可。从WebSessionContext 类中获取当前 ISession 相当简单,因为 WebSessionContext 实现了 ICurrentSessionContext 接口

10)、在实际使用中我们并不需要直接调用 WebSessionContext 的 CurrentSession() 方法,因为 ISessionFactory 提供了一个更简单的方法让我们能一步获取到 Session。

public sealed class NHibernateHelper
{
public static readonly ISessionFactory SessionFactory; static NHibernateHelper()
{
var cfg = new Configuration()
.Configure();
SessionFactory = cfg.BuildSessionFactory();
} public static ISession GetCurrentSession()
{
return SessionFactory.GetCurrentSession();
} public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}

NHibernateHelper.cs

public class NHibernateRepository<TEntity, TKey> : Repositories.IRepository<TEntity,TKey>
where TEntity: class
//where TID: struct
{
protected ISession GetCurrentSession()
{
return NHibernateHelper.GetCurrentSession();
} public TEntity GetByID(TKey id)
{
ISession session = GetCurrentSession();
return session.Get<TEntity>(id);
} public IQueryable<TEntity> GetAll()
{
ISession session = GetCurrentSession();
return session.Linq<TEntity>();
} public TKey Save(TEntity entity)
{
ISession session = GetCurrentSession();
return (TKey)session.Save(entity);
} public void Update(TEntity entity)
{
ISession session = GetCurrentSession();
session.Update(entity);
} public void Delete(TEntity entity)
{
ISession session = GetCurrentSession();
session.Delete(entity);
}
}

NHibernateRepository.cs

    public class UsersRepository: NHibernateRepository<Users, int>
{ }

UsersRepository.cs

interface IRepository<TEntity, TKey>
where TEntity : class
{
IQueryable<TEntity> GetAll();
TEntity GetByID(TKey id);
TKey Save(TEntity entity);
void Update(TEntity entity);
void Delete(TEntity entity);
}

IRepository 实现增删改查的接口

(11)、在全局Global.asax中

注意:// 并不是每一次请求都需要一个 Session 来访问数据库。

// 虽然 NHibernate 的 Session 是轻量级的,较为合理的做法是在“真正需要”时绑定。

        public MvcApplication()
{
// 并不是每一次请求都需要一个 Session 来访问数据库。
// 虽然 NHibernate 的 Session 是轻量级的,较为合理的做法是在“真正需要”时绑定。
BeginRequest += new EventHandler(MvcApplication_BeginRequest);
EndRequest += new EventHandler(MvcApplication_EndRequest);
} private void MvcApplication_BeginRequest(object sender, EventArgs e)
{
ISession session = NHibernateHelper.OpenSession();
CurrentSessionContext.Bind(session);
} private void MvcApplication_EndRequest(object sender, EventArgs e)
{
if (CurrentSessionContext.HasBind(NHibernateHelper.SessionFactory))
{
ISession session = WebSessionContext.Unbind(NHibernateHelper.SessionFactory);
//session.Flush();
session.Close();
}
}

Global.asax.cs

NHibernate的查询:

     分为以下几种:(我在项目中用的第三种方式(Linq))

  1. HQL: NHibernate配备了一种非常强大的查询语言,这种语言看上去很像SQL。但是不要被语法结构 上的相似所迷惑, HQL是非常有意识的被设计为完全面向对象的查询,它可以理解如继承、多态 和关联之类的概念。  

return _session.CreateQuery("from Customer c where c.Firstname=:fn")
.SetString("fn", firstname)
.List<Customer>();

HQL写法

2、条件查询(Criteria Query):在NHibernate中,提供了一种直观的、可扩展的Criteria API。在我们键入查询语句的时候,提供了编译时的语法检查,VS提供了强大的智能提示。如果你对HQL的语法感觉不是很舒服的话,用这种方法可能更容易。这种API也比HQL更可扩展。

public IList<Customer> Order()
{
return _session.CreateCriteria(typeof(Customer))
.Add(Restrictions.Like("Firstname","T%"))
.AddOrder(new NHibernate.Criterion.Order("Firstname", false))
.AddOrder(new NHibernate.Criterion.Order("Lastname", true))
.List<Customer>();
}

Criteria Query写法

3、Linq支持:首先得引入 using NHibernate.Linq;和之前你用的Linq是一模一样的。在NHibernate 3.0.0版本中,Query方式新增了Linq支持和强类型查询API(QueryOver)两种查询方式

 public List<Entities.Users> List()
{
var List = Session.Query<Users>().ToList();
return List;
}

Linq写法

根据前面的总结,很容易的可以在项目中使用NHibernate了,代码如下:             

      private UsersRepository repository = new UsersRepository();
//
// GET: /Employee/ public ActionResult Index()
{
IEnumerable<Users> _Users= repository.GetAll();
return View(Users);
}

获取全部数据

[HttpPost]
public ActionResult Create(Users _users)
{
try
{
repository.Save(_users);
return RedirectToAction("Index");
}
catch
{
return View(_users);
}
}

增加

[HttpPost]
public ActionResult Edit(Users _users)
{
try
{
repository.Save(_users); return RedirectToAction("Index");
}
catch
{
return View(_users);
}
}

编辑

总结:

      NHibernate不止这么简单,还有以下内容(本人研究的也不是很深,大家可以加入QQ群:331273083,进行MVC、EF、NHibernate的交流与学习,互相进步嘛):

      1、SchemaExport的工具(根据实体类生成数据库)。

2、NHibernate中使用存储过程。

3、NHibernate一级缓存、NHibernate二级缓存。

MVC Nhibernate 示例的更多相关文章

  1. 年底小回顾(MVC+NHibernate+Jquery+JqueryUI——网站)

    1.附:利用MVC+NHibernate+Jquery+JqueryUI这些技术可以做出一个比较好的前台+后台网站.下面是本人对这些技术的笔记,作为私人年底小结吧.呵呵 好久没写文章了,感觉下不了笔吐 ...

  2. “MVC+Nhibernate+Jquery-EasyUI” 信息发布系统 第六篇(图片新闻的添加以及带分页的静态页的生成)

    “MVC+Nhibernate+Jquery-EasyUI” 信息发布系统 第六篇(图片新闻的添加以及带分页的静态页的生成) 一.这篇文章主要是要实现:图片新闻的添加,无刷新图片的上传,以及添加新闻静 ...

  3. “MVC+Nhibernate+Jquery-EasyUI” 信息发布系统 第四篇(用户管理功能的实现)

    “MVC+Nhibernate+Jquery-EasyUI” 信息发布系统 第四篇(用户管理功能的实现) 一.前三篇的内容是否对您有帮助呢?如果有的话,请您继续关注这篇吧,这篇主要是实现”用户管理“的 ...

  4. “MVC+Nhibernate+Jquery-EasyUI”信息发布系统 第二篇(数据库结构、登录窗口、以及主界面)

    “MVC+Nhibernate+Jquery-EasyUI”信息发布系统 第二篇(数据库结构.登录窗口.以及主界面) 一.在上一篇文章中,主要说的就是把主框架搭建起来,并且Nhibernate能达到增 ...

  5. Spring MVC 项目示例

    Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架.Spring的web框架围绕DispatcherServlet设计, 作用是将请求分发到不同 ...

  6. “MVC+Nhibernate+Jquery-EasyUI”信息发布系统 第二篇(数据库结构、登录窗口、以及主界面)

    一.在上一篇文章中,主要说的就是把主框架搭建起来,并且Nhibernate能达到增删改查的地步.测试好之后再来看这篇文章,我的主框架相对来说简答一点,重点还是实现系统的功能,以及对Jquery-Eas ...

  7. NHibernate with ASP.NET MVC 入门示例

    目的:初步了解NHibernate的用法,包括数据库的CRUD, 基于ASP.NET MVC 项目模板 步骤: 创建ASP.NET MVC 新项目 使用NuGet引入FluentNHibernate ...

  8. 1.【转】spring MVC入门示例(hello world demo)

    1. Spring MVC介绍 Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于 ...

  9. Spring MVC 入门示例讲解

    在本例中,我们将使用Spring MVC框架构建一个入门级web应用程序.Spring MVC 是Spring框架最重要的的模块之一.它以强大的Spring IoC容器为基础,并充分利用容器的特性来简 ...

随机推荐

  1. Java Map hashCode深究

    [Java心得总结七]Java容器下——Map 在自己总结的这篇文章中有提到hashCode,但是没有细究,今天细究整理一下hashCode相关问题 1.hashCode与equals 首先我们都知道 ...

  2. 介绍,介绍我的底层支持库 Net.Sz.CFramework

    Net.Sz.CFramework  是我自己的底层库,是经过验证的底层库. 包含: socket tcp协议,socket http协议线程池,线程模型,任务模型,定时器模型,日志模块脚本模块一些辅 ...

  3. Java进击C#——开发环境

    在进入本章之前.笔者想说一些话.对于笔者来讲语言没有好坏之分.只有适不适用之别.当上一篇发到首页的时候,我突然发现有可能会引发争论.这是笔者担心的,这也是笔者不想看到的. 笔者想写这一系列的原因不是为 ...

  4. [C#项目开源] MongoDB 可视化管理工具 (2011年10月-至今)

    正文 该项目从2011年10月开始开发,知道现在已经有整整5年了.MongoDB也从一开始的大红大紫到现在趋于平淡. MongoCola这个工具在一开始定位的时候只是一个Windows版本的工具,期间 ...

  5. Fragment

    Fragment 是轻量级的,比Activity 快,适合同一个APP 内页面的跳转. 1: 在MainActivity 中启动一个fragment  BlankFragment: public cl ...

  6. flhs笔试题-回家上机实践

    这是最近参加的一个公司的笔试题,回家上机写了下代码,希望对有需要的小伙伴有用,简单实现字符串和数组在指定位置的插入: package org.flhs; import com.google.commo ...

  7. lsof命令

    学习资源https://linux.die.net/man/8/lsof lsof mean list open files 如果说linux中一切皆文件的话,那么lsof就是一盏照亮黑暗的文件系统的 ...

  8. struts2类型转换

    1. Struts2中的类型转换 我们知道通过HTTP提交到后台的数据,都是字符串的形式,而我们需要的数据类型当然不只字符串类型一种.所以,我们需要类型转换! 在Struts2中,类型转换的概念除了用 ...

  9. python学习笔记(基础三:if else流程判断、while循环、for循环)

    if else流程判断 getpass在pycharm中无法使用,在命令行窗口中进入python环境可以使用. import getpassusername = input("usernam ...

  10. Python 生成器与迭代器 yield 案例分析

    前几天刚开始看 Python ,后因为项目突然到来,导致Python的学习搁置了几天.然后今天看回Python 发现 Yield 这个忽然想不起是干嘛用的了(所以,好记性不如烂笔头.).然后只能 花点 ...