一:NHibernate简介:
NHibernate是基于Microsoft VisualStudio.Net的O/R Mapping持久框架,它从基于Java的Hibernate项目移植过来。O/R Mapping就是把对象到映射关系数据库的记录。简单的说就是能实现把一个对象存储为数据表中的一条记录和由一条记录创建一个相应的对象,数据表中的数据就是对象的属性。
NHibernate与传统的DataSet/DataTable的不同,首先表现在设计上的不同,当使用O/R Mapping时,更多的是从对象的角度设计程序,而把数据(对象的属性)存储的细节放在后面,可以完全采用面向对象(00)的方式来设计,而在使用DataSet/DataTable时,它只是存放数据的对象,看起来更像一个数据表,不能直观地表达业务概念。NHibernate用于把你的.NET对象持久化到底层的关系数据库中,你完全不用自己编写SQL语句去操作这些对象,NHibernate会替代你做这些工作。你的代码里面只需要关心这些对象,NHibernate生成SQL语句并能为你取到正确的东西。
二:NHibernate主要接口的介绍
ISession: 是面向用户的主要接口,主要用于对象持久化,数据加载等操作,支持数据库事务,它隐藏了NHibernate内部复杂的实现细节,ISession由ISessionFactory创建。
ISessionFactory:是NHibernate内部的核心类,它维护到持久机制(数据库)的连接并对它们进行管理,同时还会保存所有持久对象的映射信息。
ISessionFactory由Configuration创建,因为创建ISessionFactory的开销非常大(需要加载映射信息),所以这个对象一般使用Singleton(单例)模式。
ITransaction:是NHibernate的事务处理接口,它只是简单地封闭了底层的数据库事务。事务必须由ISession来启动。
ICriteria:是Expression(表达式)数据加载接口,Expression是一个关系表达式组合,通过它能产生SQL语句的Where部分,用户需要通过ISession来间接调用它。
IQuery:是HQL数据加载接口,HQL(Hibernate Query Language)是NHibernate专用的面向对象的数据查询语言,它与数据库的SQL有些类似,但功能更强大。同ICriteria一样,也需要通过ISession来间接调用它。
Session类:封装了NHibernate中的ISession和ISessionFactory两个接口,Session类的属性和方法都是静态的,它有一个Factory属性,用于返回ISessionFactory,有一个GetSession方法,用于取得一个新的ISession.
三:应用的步骤
1. 在数据库中创建把.Net类持久化的对应表.
2. 创建需要被持久化的.Net类.
3. 创建映射文件,以告诉NH怎样持久化这些类的属性.
4. 创建NH的配置文件,以告诉NH怎样连接数据库.
5. 使用NH提供的API.
步骤1:创建数据库表
我们正在做的是一个非常简单的NH示例.在这个例子里面,我们实现一个基本的用户管理子系统.我们将会使用一个user表(sql server 2000):
use NHibernate
go
CREATE TABLE users (
LogonID varchar(20) NOT NULL default '0',
Name varchar(40) default NULL,
Password varchar(20) default NULL,
EmailAddress varchar(40) default NULL,
LastLogon datetime default NULL,
PRIMARY KEY (LogonID)
)
go
我使用的是MS Sql Server 2000,但是如果你找到一个任何数据库的.net Data Provider驱动,你可以使用任何数据库.
步骤2:创建.Net类:
当我们这样一堆的用户的时候,我们需要某种对象来保存.NH是通过reflection对象的属性来工作的,所以我们给需要持久化的对象添加属性.一个对应于上面数据库结构的类可以写成这个样子:
using System;
namespace NHibernate.Demo.QuickStart
{
public class User
{
private string id;
private string userName;
private string password;
private string emailAddress;
private DateTime lastLogon;
public User()
{
}
public string Id
{
get { return id; }
set { id = value; }
}
public string UserName
{
get { return userName; }
set { userName = value; }
}
public string Password
{
get { return password; }
set { password = value; }
}
public string EmailAddress
{
get { return emailAddress; }
set { emailAddress = value; }
}
public DateTime LastLogon
{
get { return lastLogon; }
set { lastLogon = value; }
}
}
}
在上面的代码里面,我们把属性和构造函数写成了public-NH并不要求一定要这样做.你可以使用public,protected,internal或者干脆private来标记你的属性.
步骤3:编写映射文件(Mapping File)
现在我们有了数据库表和.Net类,我们还需要告诉NH怎样在数据库和类之间映射.这就需要映射文件了.最简捷(也是可维护性最好的)方法就是为每一个类编写一个映射文件,如果你把命名为"XXX.hbm.xml"的映射文件和XXX类文件放在同一目录下,NH会很让 一切变得很轻松.这儿,我们的User.hbm.xml可能会像这样:
注意:实体类的映射文件以.hbm.xml做为后辍,确记得把映射文件的Build Action属性设为:Embedded Resource,若则会出错,确记确记!
让我们来看看这个有趣的映射文件:第一个tag是class,这里我们把类型名(类名和Assembly名)映射到数据库中的user表(这里和hibernate有些不同,我们必须告诉NH这个类从哪儿来的.这个差异是由.Net和Java Reflect机制的不同引起的-zyyang).这种情况下,我们是从Assembly NHibernate.Demo.QuickStart中载入NHibernate.Demo.QuickStart.User类..NH遵守.Net Framework使用Reflection载入类型的规则-所以遇到什么疑惑,就去查查.NET Framework SDK.
让我们暂时跳过"id" tag,先说property节点."name"属性值就是我们写的.Net类中的属性,column属性值就是在数据库中与'Net类属性对应的字段名.type属性是可选的(如果你没有标明,NH会给出一个最适合的),但是推荐的做法是带上这个属性.hibernate用户会注意到,在type属性值里,我们给出了长度值,这是因为ADO.NET需要这样做.
让我们返回到"id" tag,你可能会猜想这个tag和映射到表的Primary Key有关.正确.ID tag的格式和Property tag的相似.我们从Property(name)映射到目标数据库的字段(colume).
这些嵌入的Generator标记告诉NH怎样生成Primary Key(NH很方便的就能给你生成一个,不管是什么类型的,只要你告诉它怎样去做).在我们举的例子中,把它设置成"assigned",意思是"我们的对象将自己生成key"(User对象将总是需要一个UserID),如果你乐意让NH代替你生成,你会对uuid.hex和uuid.string类感兴趣的(参看chm文档).
Tip:如果你使用vs.net编译,设置Build Action,把User.hbm.xml文件作为资源绑定到Asssembly,这样映射文件就成了Asssembly的一部分了.后面我们会明白这个步骤的重要性.
步骤4:创建数据库配置文件
目前为止,我们还没有告诉NH到哪儿去找数据库.最直接的方法就是在你程序的配置文件中给NH一个部分,就是这样:
上面的例子中使用SqlClient驱动,连接到本地的nhibernate数据库,并且使用提供的用户和密码.还会有其他的配置项,你可以参看文档.
步骤5:开始体验NHibernate的神奇
所有艰苦的工作已经做完了.如果所有的工作完成后,你将会有这些成果:
æ User.cs - 需要持久化的.Net类.
æ User.hbm.xml - 映射文件
æ app.config - 带有Ado.net连接信息的配置文件(你也可以在代码中指定的)
æ 一个叫做user的数据库表.
在代码里面使用NHibernate是很简单的事情:
1. 创建一个Configuration对象.
2. 告诉Configuration你想要持久化哪一种对象.
3. 创建一个Session连接到你设定的数据库.
4. 载入,保存和查询你的对象.
5. Flush()你的Session
好,让我们来看看一些代码:
创建一个Configuration对象....
Configuration对象知道所有在.Net类和后端数据库之间的映射关系,
Configuration cfg = new Configuration();
cfg.AddAssembly("NHibernate.Demo.QuickStart");
Configuration对象会查找这个Assembly中所有以.hbm.xml结尾的文件.也有其他的方法添加映射文件,这个可能是最简单的一个.
创建一个Session对象.......
ISession对象代表着一个到后端数据库连接,ITransaction代表一个NHibernate管理的事务(Transaction).
ISessionFactory factory = cfg.BuildSessionFactory();
ISession session = factory.OpenSession();
ITransaction transaction = session.BeginTransaction();
载入,保存和查询你的对象......
现在你可以以.net的方式对待这些对象.想在数据库中保存一个新的user?只需要:
User newUser = new User();
newUser.Id = "joe_cool";
newUser.UserName = "Joseph Cool";
newUser.Password = "abc123";
newUser.EmailAddress = "";
newUser.LastLogon = DateTime.Now;
// Tell NHibernate that this object should be saved
session.Save(newUser);
// commit all of the changes to the DB and close the ISession
transaction.Commit();
session.Close();
这就是NH的好处,大部分时间内你只用关心你的业务对象(BO).
假如你需要根据已经知道的user ID查询一个对象,如果session是open的,你只需要一行:
// open another session to retrieve the just inserted user
session = factory.OpenSession();
User joeCool = (User)session.Load(typeof(User), "joe_cool");
这样你又会得到这个对象,设置一下对象的属性,它会在下一次Flush()方法出现的时候被持久化到数据库.
// set Joe Cool's Last Login property
joeCool.LastLogon = DateTime.Now;
// flush the changes from the Session to the Database
session.Flush();
让NH去写入你对对象作出的修改,你只需要Flush Session就可以了.
更好的是,你可以从数据库中查询到一个System.Collections.IList:
IList userList = session.CreateCriteria(typeof(User)).List();
foreach(User user in userList)
{
Console.WriteLine(user.Id + " last logged in at " + user.LastLogon);
}
这个查询会返回整个表的内容.尤其是当你想要更多的控制时候--像类出所有在March 14, 2004 10:00 PM之后登陆过的用户,你可以:
IList recentUsers = session.CreateCriteria(typeof(User)).Add(Expression.Gt("LastLogon", new DateTime(2004, 03, 14, 20, 0, 0))).List();
foreach(User user in recentUsers)
{
Console.WriteLine(user.Id + " last logged in at " + user.LastLogon);
}
文档里还有很多的查询选项,但是以上这些足够让你看出Hinernate的力量了.
不要忘记了,最后要关掉你的Session.
// tell NHibernate to close this Session
session.Close();
| | | | |
阅读(1465) | 评论(0) | 转发(0) |