NHibernate是一个面向.NET环境的对象/关系数据库映射工具。对象/关系数据库映射(object/relational mapping,ORM)这个术语表示一种技术,用来把对象模型表示的对象映射到基于SQL的关系模型数据结构中去。——百度百科
简介
从网上找到下面的一张图,自认为这张图相当好:
简单的说ORM,能够达到这样一种效果:我们不用去知道数据库(R)的内容,系统根据M,通过对对象(O)的操作,自动完成访问数据库。例如要完成“根据ID查询”,我们对对象使用了Get<Customer>(customerId),完成的就是这样的SQL语句:select * from Customer where [email protected]
很显然,带来了这两点最直观的表现:
- “解耦”:写代码时,我们不用去管数据怎样,不用去写SQL语句。
- OO:更符合面象对象的思想,对表的操作,都转化成对对象的操作。
对于NHibernate,网上有这样一段评价:
什么是优雅?动态设置,避免hardcode,就是优雅;层次清晰,层次间耦合最低,就是优雅;只写一处,处处引用,就是优雅;代码精炼,避免过度设计,就是优雅;接口明确,调用简单,就是优雅;调试容易,便于测试,就是优雅。。。。。。而优雅的设计和实现,在可扩展性、可维护性、开发效率、开发成本等方面都是最好的。
Hibernate就是优雅的设计,它通过配置文件,建立实体与数据库的映射,动态的生成SQL语句,避免了对属性字段的hardcode,这就是它最本质的思想。
Demo结构
对ORM就简要介绍到这。光说不练嘴把式,下面开始我们的第一个NHibernate程序。先宏观的看一下我们这个Demo:
各层说明:
- DomainModel(领域模型):用于持久化类和O/R Mapping操作
- DAL(Data Access Layer数据访问层):定义对象的CRUD操作
- NUnitTest:对数据访问层的测试,这里我使用Nunit单元测试框架
项目引用(本程序比较简单,NHibernate相关程序集,只用到了Nhibernate.dll):
- DAL:引用NHibernate.dll,和Domain
- Data.Test:引用NHibernate.dll和nunit.framework.dll程序集(测试框架),Domain和DAL引用
五部曲
接下来,是本文的重点,通过五步(传说中的五部曲)就能完成操作:
- 在数据库中创建把.Net类持久化的对应表.(可以不用建表,通过映射自动创建对应的表,但必须先建好数据库)
- 创建需要被持久化的.Net类.
- 创建映射文件, 告诉NHibernate怎样持久化这些类的属性.
- 创建NHibernate的配置文件,以告诉NH怎样连接数据库.
- 使用NHibernate提供的API.
一、建数据库(略)
二、编写持久化类
新建一个Customer.cs类文件:
namespace DomainModel.Entities { public class Customer { public virtual int CustomerId { get; set; } public virtual String FirstName { get; set; } public virtual String LastName { get; set; } } }规则:NHibernate使用属性的getter和setter来实现持久化。
注意:要求该实体类,一定不能为sealed类型,类中的字段要设置为virtual。
三、编写映射文件
NHibernate要知道怎样去加载和存储持久化类的对象。这正是NHibernate映射文件发挥作用的地方。映射文件包含了对象/关系映射所需的元数据。元数据包含持久化类的声明和属性到数据库的映射。映射文件告诉NHibernate它应该访问数据库里面的哪个表及使用表里面的哪些字段。
这里,我为Customer.cs类编写映射文件。新建一XML文件,命名为Customer.hbm.xml:
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0"> <class name="DomainModel.Entities.Customer, DomainModel" table="Customer"> <id name="Id" type="Int32" unsaved-value="null"> <column name="CustomerId" length="4" sql-type="int" not-null="true" unique="true"/> <generator class="native" /> </id> <property name="Firstname" type="String"> <column name="Firstname" length="50" sql-type="nvarchar" not-null="false"/> </property> <property name="Lastname" type="String"> <column name="Lastname" length="50" sql-type="nvarchar" not-null="false"/> </property> </class> </hibernate-mapping>提示:我们要为Microsoft Visual Studio 2012添加编写NHibernate配置文件智能提示的功能。只要在下载的NHibernate里找到configuration.xsd和nhibernate-mapping.xsd两个文件并复制到C:\Program Files (x86)\Microsoft Visual Studio 11.0\Xml\Schemas目录即可。
注意:XML文件的默认生成操作为“内容”,这里需要修改为“嵌入的资源”生成,因为NHibernate是通过查找程序集中的资源文件映射实体。
四、配置Nhibernate
我们可以几种方法来保存NHibernate的配置,具体以后来介绍,这里我们使用hibernate.cfg.xml文件来配置,不过不必担心,这个文件我们可以在src\NHibernate.Config.Templates文件夹下找到,直接复制到Data.Test中修改一下配置信息和文件输出属性就可以了。
注意:XML文件的默认“复制到输出目录”为“不复制”,这里需要修改为“始终复制”。
五、使用NHibernate提供的API
1)辅助类
我们现在可以开始NHibernate了。首先,我们要从ISessionFactory中获取一个ISession(NHibernate的工作单元)。ISessionFactory可以创建并打开新的Session。一个Session代表一个单线程的单元操作。 ISessionFactory是线程安全的,很多线程可以同时访问它。ISession不是线程安全的,它代表与数据库之间的一次操作。ISession通过ISessionFactory打开,在所有的工作完成后,需要关闭。
ISessionFactory通常是个线程安全的全局对象,只需要被实例化一次。我们可以使用GoF23中的单例(Singleton)模式在程序中创建ISessionFactory。这个实例我编写了一个辅助类NHibernateHelper 用于创建ISessionFactory并配置ISessionFactory和打开一个新的Session单线程的方法,之后在每个数据操作类可以使用这个辅助类创建ISession 。public class SessionManager { private ISessionFactory _sessionFactory; public SessionManager() { _sessionFactory = GetSessionFactory(); } private ISessionFactory GetSessionFactory() { return (new Configuration()).Configure().BuildSessionFactory(); } public ISession GetSession() { return _sessionFactory.OpenSession(); } }2)编写操作
在Data中新建一类NHibernateSample.cs,编写一方法GetCustomerId用于读取客户信息。在编写方法之前,我们需要初始化Session。
protected ISession Session { get; set; } public NHibernateSample(ISession session) { Session = session; }NHibernate有不同的方法来从数据库中取回对象。最灵活的方式是使用NHibernate查询语言(HQL),是完全基于面向对象的SQL。
public void CreateCustomer(Customer customer) { Session.Save(customer); Session.Flush(); } public Customer GetCustomerById(int customerId) { return Session.Get<Customer>(customerId); }测试
好了,终于可以使用我们的方法了,这里新建一个测试类NHibernateSampleFixture.cs来编写测试用例:调用NHibernateSample类中GetCustomerId方法查询数据库中CustomerId为1的客户,判断返回客户的Id是否为1。
结语
在此章中,我们使用NHibernate来构建了一个最基本的项目,没有体现NHibernate更多细节,只描绘了NHibernate的基本面目。当然使用NHibernate有各种各样的程序架构,我按照一般模式构建的。
资料下载:
博客参考:
《快速生成NHibernate的映射文件和映射类的利器 —— codesmith软件》