NHibernate之旅(2):开始使用NHibernate
2010-10-26 19:55
197 查看
我们亲自动手,来一步一步搭建一个NHibernate程序来,我以一个实际场景电子交易程序来模拟,客户/订单/产品的经典组合。由于是第一次使用NHibernate,所以我们的目的是映射一张表并完成使用NHibernate来读取数据,下面的一幅图片给了我们第一印象。我们按照基本开发软件思想的流程一步一步完成。
我使用的开发环境:Microsoft Visual Studio 2008 SP1、SQL Server 2008 Express、NHibernate 2.0最新版。
注:源码中附有创建数据库脚本。
使用VS2008创建C#类库的项目,命名为NHibernateSample。打开项目文件夹,在其项目文件目录上新建lib文件夹,把下载NHibernate相关程序集文件拷贝到lib文件夹下。如下图:
创建项目,结构如下:
DomainModel(域模型):用于持久化类和O/R Mapping操作
DAL(Data Access Layer数据访问层):定义对象的CRUD操作
DAL.Test(数据访问层测试):对数据访问层的测试,这里我使用Nunit单元测试框架
项目引用
DomainModel:引用Iesi.Collections.dll程序集(Set集合在这个程序集中)
DAL:引用NHibernate.dll和Iesi.Collections.dll程序集,DomainModel层引用
DAL.Test:引用NHibernate.dll和Iesi.Collections.dll程序集,nunit.framework.dll程序集(测试框架),DomainModel层和DAL层引用
现在为Customer编写持久化类来映射成为数据库表。新建一个Customer.cs类文件:
规则
NHibernate使用属性的getter和setter来实现持久化。
属性可设置为public、internal、protected、protected internal或private
注意NHibernate默认使用代理功能,要求持久化类不是sealed的,而且其公共方法、属性和事件声明为virtual。在这里,类中的字段要设置为virtual,否则出现“failed: NHibernate.InvalidProxyTypeException : The following types may not be used as proxies: DomainModel.Entities.Customer: method get_CustomerId should be virtual,method set_CustomerId should be virtual”异常。
NHibernate要知道怎样去加载和存储持久化类的对象。这正是NHibernate映射文件发挥作用的地方。映射文件包含了对象/关系映射所需的元数据。元数据包含持久化类的声明和属性到数据库的映射。映射文件告诉NHibernate它应该访问数据库里面的哪个表及使用表里面的哪些字段。
这里,我为Customer.cs类编写映射文件,具体怎么编写O/R Mapping文件,请参考NHibernate文档。新建一XML文件,命名为Customer.hbm.xml:
注意XML文件的默认生成操作为“内容”,这里需要修改为“嵌入的资源”生成,使用.NET Reflector查看程序集:
否则出现“ failed: NHibernate.MappingException : No persister for: DomainModel.Entities.Customer”异常。
NHibernate有不同的方法来从数据库中取回对象。最灵活的方式是使用NHibernate查询语言(HQL),是完全基于面向对象的SQL。
注意XML文件的默认“复制到输出目录”为“不复制”,这里需要修改为“始终复制”。否则出现“failed: NHibernate.Cfg.HibernateConfigException : An exception occurred during configuration of persistence layer. ----> System.IO.FileNotFoundException : 未能找到文件“NHibernateSample\DAL.Test\bin\Debug\hibernate.cfg.xml””异常。
我们使用TestDriven.NET测试一下这个方法:OK,测试通过,还输出了SQL语句(注:我配置NHibernate时设置了show_sql=true输出SQL语句)。
本系列链接:NHibernate之旅系列文章导航
NHibernate Q&A
欢迎加入NHibernate中文社区,一起讨论NHibernate知识!
请到NHibernate中文社区下载本系列相关源码。
下次继续分享NHibernate!
我使用的开发环境:Microsoft Visual Studio 2008 SP1、SQL Server 2008 Express、NHibernate 2.0最新版。
1.获取NHibernate
使用官方2008年9月29日最新发布的NHibernate-2.0.1.GA版本。你可以到这里下载获得NHibernate最新版本。到这里下载获得NHibernate Contrib最新版本。2.建立数据库表
打开SQL Server Management Studio,新建一个新的数据库NHibernateSample,创建四个表:分别为客户表、订单表、订单产品表、产品表。注:源码中附有创建数据库脚本。
3.创建C#类库项目
注意为什么创建C#类库项目呢?在现在软件设计中,大多数都是采用多层架构来设计,比较经典的三层架构(页面表示层,业务逻辑层,数据访问层)通常而言业务逻辑层和数据访问层都是使用类库设计,页面表示层用Web应用程序设计,它引用业务逻辑层和数据访问层类库DLL程序集。使用VS2008创建C#类库的项目,命名为NHibernateSample。打开项目文件夹,在其项目文件目录上新建lib文件夹,把下载NHibernate相关程序集文件拷贝到lib文件夹下。如下图:
创建项目,结构如下:
DomainModel(域模型):用于持久化类和O/R Mapping操作
DAL(Data Access Layer数据访问层):定义对象的CRUD操作
DAL.Test(数据访问层测试):对数据访问层的测试,这里我使用Nunit单元测试框架
项目引用
DomainModel:引用Iesi.Collections.dll程序集(Set集合在这个程序集中)
DAL:引用NHibernate.dll和Iesi.Collections.dll程序集,DomainModel层引用
DAL.Test:引用NHibernate.dll和Iesi.Collections.dll程序集,nunit.framework.dll程序集(测试框架),DomainModel层和DAL层引用
4.编写DomainModel层
4-1.编写持久化类
按简单传统.NET对象(POCOs,Plain Old CLR Objects(Plain Ordinary CLR Objects))模型编程时需要持久化类,也可以说是DTO(Data Transfer Object,数据传送对象)模式(这是迄今为止可以工作的最简单方式)。在NHibernate中,POCO通过.NET的属性机制存取数据,就可以把它映射成为数据库表。现在为Customer编写持久化类来映射成为数据库表。新建一个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来实现持久化。
属性可设置为public、internal、protected、protected internal或private
注意NHibernate默认使用代理功能,要求持久化类不是sealed的,而且其公共方法、属性和事件声明为virtual。在这里,类中的字段要设置为virtual,否则出现“failed: NHibernate.InvalidProxyTypeException : The following types may not be used as proxies: DomainModel.Entities.Customer: method get_CustomerId should be virtual,method set_CustomerId should be virtual”异常。
4-2.编写映射文件
小提示我们要为Microsoft Visual Studio 2008添加编写NHibernate配置文件智能提示的功能。只要在下载的NHibernate里找到configuration.xsd和nhibernate-mapping.xsd两个文件并复制到X:\Program Files\Microsoft Visual Studio 9.0\Xml\Schemas目录即可。NHibernate要知道怎样去加载和存储持久化类的对象。这正是NHibernate映射文件发挥作用的地方。映射文件包含了对象/关系映射所需的元数据。元数据包含持久化类的声明和属性到数据库的映射。映射文件告诉NHibernate它应该访问数据库里面的哪个表及使用表里面的哪些字段。
这里,我为Customer.cs类编写映射文件,具体怎么编写O/R Mapping文件,请参考NHibernate文档。新建一XML文件,命名为Customer.hbm.xml:
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DomainModel" namespace="DomainModel"> <class name ="DomainModel.Entities.Customer,DomainModel" table="Customer"> <id name="CustomerId" column="CustomerId" type="Int32" unsaved-value="0"> <generator class ="native"></generator> </id> <property name="Firstname" column ="Firstname" type="string" length="50" not-null="false"/> <property name ="Lastname" column="Lastname" type="string" length="50" not-null="false"/> </class> </hibernate-mapping>
注意XML文件的默认生成操作为“内容”,这里需要修改为“嵌入的资源”生成,使用.NET Reflector查看程序集:
否则出现“ failed: NHibernate.MappingException : No persister for: DomainModel.Entities.Customer”异常。
5.编写数据访问层
5-1.辅助类
我们现在可以开始NHibernate了。首先,我们要从ISessionFactory中获取一个ISession(NHibernate的工作单元)。ISessionFactory可以创建并打开新的Session。一个Session代表一个单线程的单元操作。 ISessionFactory是线程安全的,很多线程可以同时访问它。ISession不是线程安全的,它代表与数据库之间的一次操作。ISession通过ISessionFactory打开,在所有的工作完成后,需要关闭。 ISessionFactory通常是个线程安全的全局对象,只需要被实例化一次。我们可以使用GoF23中的单例(Singleton)模式在程序中创建ISessionFactory。这个实例我编写了一个辅助类SessionManager 用于创建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(); } }
5-2.编写操作
在DAL层新建一类NHibernateSample.cs,编写一方法GetCustomerId用于读取客户信息。在编写方法之前,我们需要初始化Session。private ISession _session; public ISession Session { set { _session = value; } } public NHibernateSample(ISession session) { _session = session; }
NHibernate有不同的方法来从数据库中取回对象。最灵活的方式是使用NHibernate查询语言(HQL),是完全基于面向对象的SQL。
public Customer GetCustomerById(int customerId) { return _session.Get<Customer>(customerId); }
6.编写数据访问层的测试
6-1.配置NHibernate
我们可以几种方法来保存NHibernate的配置,具体以后来介绍,这里我们使用hibernate.cfg.xml文件来配置,不过不必担心,这个文件我们可以在\src\NHibernate.Test文件夹下找到,直接复制到DAL.Test中修改一下配置信息和文件输出属性就可以了。<?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=.\SQLEXPRESS;Initial Catalog=NHibernateSample; Integrated Security=True;Pooling=False </property> <property name="adonet.batch_size">10</property> <property name="show_sql">true</property> <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property> <property name="use_outer_join">true</property> <property name="command_timeout">10</property> <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property> <mapping assembly="DomainModel"/> </session-factory> </hibernate-configuration>
注意XML文件的默认“复制到输出目录”为“不复制”,这里需要修改为“始终复制”。否则出现“failed: NHibernate.Cfg.HibernateConfigException : An exception occurred during configuration of persistence layer. ----> System.IO.FileNotFoundException : 未能找到文件“NHibernateSample\DAL.Test\bin\Debug\hibernate.cfg.xml””异常。
6-2.测试
好了,终于可以使用我们的方法了,这里新建一个测试类NHibernateSampleFixture.cs来编写测试用例:调用NHibernateSample类中GetCustomerId方法查询数据库中CustomerId为1的客户,判断返回客户的Id是否为1。using NUnit.Framework; using DomainModel.Entities; using NHibernate; namespace DAL.Test { [TestFixture] public class NHibernateSampleFixture { private ISession _session; private SessionManager _helper; private NHibernateSample _sample; [TestFixtureSetUp] public void TestFixtureSetup() { _helper = new SessionManager(); } [SetUp] public void Setup() { _session = _helper.GetSession(); _sample = new NHibernateSample(_session); } [Test] public void GetCustomerByIdTest() { Customer customer = _sample.GetCustomerById(1); int customerId = customer.CustomerId; Assert.AreEqual(1,customerId); } } }
我们使用TestDriven.NET测试一下这个方法:OK,测试通过,还输出了SQL语句(注:我配置NHibernate时设置了show_sql=true输出SQL语句)。
结语
在这篇文章中,我们使用NHibernate来构建了一个最基本的项目,没有体现NHibernate更多细节,只描绘了NHibernate的基本面目。当然使用NHibernate有各种各样的程序架构,我按照一般模式构建的。本系列链接:NHibernate之旅系列文章导航
NHibernate Q&A
欢迎加入NHibernate中文社区,一起讨论NHibernate知识!
请到NHibernate中文社区下载本系列相关源码。
下次继续分享NHibernate!
相关文章推荐
- 开始使用NHibernate
- TeeChart For VCL/FMX V2017使用教程:第一章-准备开始
- 开始使用委托
- CreateJS开始使用文档翻译
- 今天开始使用unity 5.3 进行学习编程
- NHibernate使用入门(五)
- NHibernate+WCF项目实战(二)使用NHibernate实现数据访问并进行单元测试
- 开始使用Mac OS X——写给Mac新人
- 开始使用Adobe Scout
- 今天起开始使用博客园的博客
- NHibernate使用入门(六)
- 1.开始使用Xamarin.Forms
- 开始使用C++异常
- 开始hadoop前的准备:ubuntu学习笔记-基本环境的搭建(ssh的安装,SecureCRT连接,vim的安装及使用、jdk的安装)
- 开始学习requirejs+easyui的使用.
- spring3使用task:annotation-driven开始定时
- Android中关于Volley的使用(五)从RequestQueue开始来深入认识Volley
- tableviewcell xib 使用 autolayout 从 -8 开始
- 正式开始使用这个blog了
- 使用PostSharp开始AOP