一 NHibernate简介
Nhibernate是基于ms.net的O/R Mapping持久框架,它从基于Java的Hibernate项目移植而来。O/R Mapping就是把对象到映射关系数据库的记录,简单的说就是能实现把一个对象存储为数据表中的一条记录和由一条记录创建一个相应的对象,数据表中的数据就是对象的属性。
那么为什么要使用O/R Mapping?它与传统的DataSet/DataTable又有什么不同了?
首先是设计上的不同,当使用O/R Mapping时,更多的是从对象的角度来设计程序,而把数据(对象的属性)存储的细节放在后面, 可以完全采用面向对象(OO)的方式来设计,而在使用DataSet/DataTable时,它只是存放数据的对象,看起来更像一个数据表,不能直观的表达业务概念
二 NHibernate中主要接口的介绍
ISession
ISession是面向用户的主要接口,主要用于对象持久化,数据加载等操作,支持数据库事务,它隐藏了NHB内部复杂的实现细节,ISession由ISessionFactory创建。
ISessionFactory
ISessionFactory是NHB内部的核心类,它维护到持久机制(数据库)的连接并对它们进行管理,同时还会保存所有持久对象的映射信息。
ISessionFactory由Configuration创建,因为创建ISessionFactory的开销非常大(需要加载映射信息),所以这个对象一般使用Singleton(单例)模式。
ITransaction
ITransaction是NHB的事务处理接口,它只是简单的封装了底层的数据库事务。
事务必须由ISession来启动。
ICriteria
ICriteria是Expression(表达式)数据加载接口,Expression是一个关系表达式组合,通过它能产生SQL语句的Where部分, 用户需要通过ISession来间接调用它。
IQuery
IQuery是HQL数据加载接口,HQL(Hibernate Query Language)是NHB专用的面向对象的数据查询语言,它与数据库的SQL有些类似,但功能更强大!同ICriteria一样,也需要通过ISession来间接调用它。
三 HQL数据加载
NH中,HQL是一个十分强大的面向对象的查询语言,简单的说,就是不需要使用实际的表名和列名来查询数据,而改用类名和属性。
有两种方式来执行HQL数据加载,一种是直接使用ISession的Find方法,另一种是使用IQuery接口。
IQuery最终还是会调用ISession的Find方法,下面来分析一下IQuery中HQL语句的处理.
示例代码:
1、 IQuery query = session.CreateQuery( " from User u where u.Name = :Name " )
query.SetString( "Name", "billy" );
IList users = query.List();
2、 IList users = session.Find(" from User u where u.Name = ‘billy");
四 NHibernate数据加载之Criteria加载
Criteria是通过一组条件表达式(Expression)来加载数据的,它返回满足条件的对象集合。
主要接口为ICriteria,实现为CriteriaImpl类,此类加有Internal修饰,因此不能在程序集外显示创建,nhibernate在session对象中为我们提供了一个方法CreateCriteria,此方法返回ICriteria接口。
这里列出了ICriteria接口的一些方法:
SetMaxResults:设置返回的最大结果数,可用于分页;
SetFirstResult:设置首个对象返回的位置,可用于分页;
SetTimeout:设置操作的超时值,此值将传递给IDbCommand对象;
Add:加入条件表达式(Expression对象),此方法可多次调用以组合多个条件;
AddOrder:加入排序的字段(Order对象);
List:返回满足条件的对象集合。
Criteria数据加载的关键就在Expression对象上,此对象组成了查询语句的where部分。
Expression是一个abstract(抽象)类,它通过一组static方法实现Factory Method(工厂方法)模式,这些static方法返回的都是Expression类的子类,下面列出一些常用的:
Eq:返回EqExpression,这是一个相等判断的表达式;
Like:返回LikeExpression,这是一个like判断的表达式;
Gt:返回GtExpression,这是一个大于判断的表达式;
And:返回AndExpression,这是两个表达式And操作后的表达式;
Or:返回OrExpression,这是两个表达式Or操作后的表达式;
更多的Expression请参考相关文档或源代码。
下面以几个例子来说明Criteria数据加载的用法:
1. 取得用户名(username)为billy的用户对象:
Expression ex = Expression.Eq( "Username", "billy" );
IList users = session.CreateCriteria(typeof(User)).Add( ex ).List();
2.取得用户名(username)为billy, 密码为123456的用户对象
Expression ex = Expression.And( Expression.Eq("Username", "billy"),
Expression.Eq("Password", "123456") );
IList users = session.CreateCriteria(type(User)).Add( ex ).List();
3. 取得数据中第20-40的用户对象。
IList users = session.CreateCriteria(typeof(User)) .SetFirstResult(20).SetMaxResults(40) .List();
对于SQLSERVER,数据定位采用的是IDataReader前滚至firstResult处,然后取maxResults条记录。
4. 取得按注册日期(Regdate)降序排序后的用户对象.
ICriteria c = session.CreateCriteria(typeof(User));
IList users = c.AddOrder( Order.Desc("Regdate") ).List();
五 多表关联的查询
1、添加持久化类
1〉、创建持久化类:
public class AssociateJoinIssues
{ int _issueID;
public int IssueID
{
get { return _issueID; }
set { _issueID = value; }
}
string _IssueSubject;
public string IssueSubject
{ get { return _IssueSubject; }
set { _IssueSubject = value; }
}
string _IssueDetectedDate;
public string IssueDetectedDate
{ get { return _IssueDetectedDate; }
set { _IssueDetectedDate = value; }
}
string _IssueLastestResponseDate;
public string IssueLastestResponseDate
{
get { return _IssueLastestResponseDate; }
set { _IssueLastestResponseDate = value; }
}
string _CreatedDate;
public string CreatedDate
{
get { return _CreatedDate; }
set { _CreatedDate = value; }
}
string _CreatedUser;
public string CreatedUser
{ get { return _CreatedUser; }
set { _CreatedUser = value; }
}
public AssociateJoinIssues(int IssueID, string IssueSubject, DateTime IssueDetectedDate, Nullables.NullableDateTime IssueLastestResponseDate, DateTime CreatedDate, string CreatedUser)
{
this._issueID = IssueID;
this._IssueSubject = IssueSubject;
this._IssueDetectedDate = IssueDetectedDate.ToShortDateString();
this._IssueLastestResponseDate = IssueLastestResponseDate.ToString();
this._CreatedDate = CreatedDate.ToShortDateString();
this._CreatedUser = CreatedUser;
}
}
2〉 、影射文件里添加持久化类的引用
RIssues.hbm.xml
<import class="pbe2.NHEntities.AssociateJoinIssues, pbe2.NHEntities"/>
3〉、查询语句
public IList RetrieveSpecifiedIssues(int AssociateItemid, string AssociateItem, int issueStatus)
{
ISession vSession = HibernateUtil.Session();
string hql = "select new AssociateJoinIssues(i.Issueid,i.IssueSubject,i.IssueDetectedDate,"
+ "i.IssueLastestResponseDate,i.CreatedDate,u.UserDisplayName) from RIssues as ri join ri.Issueid as i join ri.Issueid.CreatedByUserid as u "
+ " where ri.AssociateItem=:aitem and ri.AssociateItemid=:aitemid and i.IssueStatus=:issueStatus";
IQuery query = vSession.CreateQuery(hql);
query.SetString("aitem", AssociateItem);
query.SetInt32("aitemid", AssociateItemid);
query.SetInt32("issueStatus", issueStatus);
IList Results = query.List();
return Results;
}
六 删除
1、删除主表中的记录,首先要删除它的关联表中的记录
之后再删除主表中的记录
Parent p = session.Load( typeof( Parent ), pid ) as Parent;
Child c = null;
foreach( Child child in p.Children )
{
c = child;
p.Children.Remove( c );
c.Parent = null;
session.Delete( c );
session.Delete(p);
}
2、级联删除很少使用(删除主表记录时自动去删除子表记录)
七 修改
1、
private bool UpdateObjectiveCompletion(ArrayList arrList, int objectiveID)
{
ISession vSession = HibernateUtil.Session();
OmObjectives omObjective = vSession.Load(typeof(OmObjectives), objectiveID) as OmObjectives;
omObjective.Objectivepid = omObjective.Objectivepid;
omObjective.ObjectiveCode = omObjective.ObjectiveCode;
omObjective.ObjectiveSubject = omObjective.ObjectiveSubject;
omObjective.ObjectiveDesc = omObjective.ObjectiveDesc;
omObjective.ObjectiveStartDate = omObjective.ObjectiveStartDate;
omObjective.ObjectiveEndDate = omObjective.ObjectiveEndDate;
omObjective.ObjectiveLastingDays = omObjective.ObjectiveLastingDays;
omObjective.SystemOptionItemGradeid = omObjective.SystemOptionItemGradeid;
omObjective.SystemOptionItemTypeid = omObjective.SystemOptionItemTypeid;
omObjective.CreatedDate = omObjective.CreatedDate;
omObjective.CreatedByUserid = omObjective.CreatedByUserid;
omObjective.ObjectiveWeight = omObjective.ObjectiveWeight;
omObjective.ObjectiveQuota = omObjective.ObjectiveQuota;
omObjective.OrgUnitid = omObjective.OrgUnitid;
omObjective.Userid = omObjective.Userid;
omObjective.ObjectiveCompletionAmount = decimal.Parse(arrList[0].ToString());
omObjective.ObjectiveCompletionPercentage = int.Parse(arrList[1].ToString());
omObjective.ObjectiveCompletionDate = Convert.ToDateTime(arrList[2].ToString());
omObjective.ObjectiveStatus = 4;
vSession.Update(omObjective);
return true;
}
2、
private bool UpdateObjectiveCompletion(ArrayList arrList, int objectiveID)
{
ISession vSession = HibernateUtil.Session();
OmObjectives omObjective = vSession.Load(typeof(OmObjectives), objectiveID) as OmObjectives;
omObjective.ObjectiveCompletionAmount = decimal.Parse(arrList[0].ToString());
omObjective.ObjectiveCompletionPercentage = int.Parse(arrList[1].ToString());
omObjective.ObjectiveCompletionDate = Convert.ToDateTime(arrList[2].ToString());
omObjective.ObjectiveStatus = 4;
vSession.Save(omObjective);
return true;
vSession.Close();
}
3、注意:
多个表关联时,要用一个Session,事务才有效。
八NHibernate中DateTime,int,bool空值的处理方法
我们知道,数据库中DateTime子段允许为空(null)。当我们在ASP.NET中映射为DateTime是就不允为空了。该怎么处理?基本有两种办法:
1、修改.hbm.xml文件中的类型,该"DateTime"为"String",该实体文件中的属性类型"DateTime"为"String"。
处理的时候,该属性值要么为空,要么是具有正确日期格式的字符串。
该方法只适合DateTime类型,而对int,bool类型就不适应了。下面就看第二种方法。
2、Nullables处理
(1)添加引用:Nullables.dll与Nullables.NHibernate.dll
NHibernate.Mapping.Attributes.dll
(2)修改配置文件.hbm.xml对应的类型,如:
<property name="InDate" column="inDate" type="DateTime"/>修改为:
<property name="InDate" column="inDate" type="Nullables.NHibernate.NullableDateTimeType,Nullables.NHibernate"/>
(3)修改实体类文件,如:
private DateTime _inDate;
/// <summary>
/// 添加日期
/// </summary>
public DateTime InDate
{
get { return _inDate; }
set { _inDate = value;
} 修改为:
private Nullables.NullableDateTime _InDate;
/// <summary>
/// 添加
/// </summary>
[NHibernate.Mapping.Attributes.Property]
public Nullables.NullableDateTime InDate
{
get { return _InDate; }
set { _InDate = value; }
}
(4)给属性InDate赋值:
Item clsItem = new Item();
clsItem.InDate = new NullableDateTime(System.DateTime.Now);
如果要输入空值,如:clsItem.InDate = nulll;
(5)获取属性InDate的值:
ItemCRUD clsCRUD = new ItemCRUD(); //对实体类的操作
Item clsItem = clsCRUD.ItemDetails(id); //获取实体类
this.txtInDate.Text = clsItem.InDate.ToString();
通过第二种方法可以对数据库中对应的整形、bool类型等赋空值。