2进阶
2.1 the Plain Old CLR Object (POCO)
实体类属性必须用get,set方法;
必须用不带参数的默认的构造器;
如果要判定实体类的两个实例相等,也就是说是数据库中的同一条记录,必须在实体类中override Equals().
2.2 ont-to-many
在进行保存时候用SaveOrUpdateCopy。
在Cat端设置lazy=true,则在查询时候,只要不访问Cat类的LIST对象,如CatTvPlans,它就不会执行SELECT语句,也就是不会从数据库取值并赋值。
2.3 处理数据库自增量标识种子
2.3.1 方式一
首先实体类如常增加属性,如:
public virtual int oId
{
get { return oid; }
set { oid = value; }
}
Cat.hbm.xml该节点为:
<property name="oId" insert="false" update="false"/>
使用自增属性的时候,在一次有效的客户端连接内,使用SCOPE_IDENTITY()也可以得到自增ID的值。
2.3.2 方式二
在配置文件中
<id name="oId" type="Int32">
<generator class="identity" />
</id>
表示Id是主键字段,generator是生成器,这里是使用SqlServer中内置标识字段来生成。
2.4 使用事务
如果你的代码中需要事务,只需要把代码稍微修改一下。
代码示例(改变了数据库中的数据,数据的增删改):
//配置Configuration
Configuration cfg = new Configuration().Configure();
//创建ISessionFactory
ISessionFactory factory = cfg.BuildSessionFactory();
//定义事务
ITransaction tx = null;
//打开ISession
ISession session = factory.OpenSession();
try
{
//开始事务
tx = session.BeginTransaction();
在这里添加操作
tx.Commit();
}
catch(HibernateException ex)
{
if (tx!=null) tx.Rollback();
throw ex;
}
finally
{
//关闭ISession
session.Close();
}
我一般在不影响数据的方法(例如:查询)中不包含事务,而影响数据的方法(例如:增删改)使用事务。
2.5数据库操作方法详解
数据库操作指南
注意:
1:需认真查看数据库表约束和关系
2:hbm.xml的每个属性均有用,不能随意更改
3:一个猫只允许有一个伴侣,有多个演出计划,穿衣方案和食物方案。其约束可查看数据库表约束。
若更改了数据库结构,需重新设计hbm.xml和实体类
======================================================
1:猫的种类CatType的添加:
2:CatType使用聚合函数,如count:
3:CatType使用聚合函数,如max:
4:增加一只猫Cat,名为JACK:
5:增加一只猫Cat,名为TOM,种类为xianluo,同时为该猫增加一个伴侣,名为MARY,cat和catPart进行one-to-one映射:
6:为名为jack的那只猫,增加一个伴侣rose:
7:为名为jack的那只猫,增加2个演出计划CatTvPlan:
8:增加猫john,同时增加1个演出计划CatTvPlan,2个穿衣方案CatDressScheme,3个食物方案CatFoodScheme:
9:查询猫john,同时查出其所有的演出计划CatTvPlan,穿衣方案CatDressScheme,食物方案CatFoodScheme:
10:只查询猫john,不同时查出其所有的演出计划CatTvPlan,穿衣方案CatDressScheme,食物方案CatFoodScheme: (这里需要注意到是,只要不访问Cat类的LIST对象,如CatTvPlans,它就不会执行SELECT语句,也就是不会从数据库取值并赋值。) 但是,lazy="true" cascade="all-delete-orphan"
11:将猫john改名为jordan
12:将猫jordan的穿衣方案删除,一次删除一个
13:将猫jordan的演出计划和食物方案全部删除
2.5.1 页面代码
<div>
1:猫的种类CatType的添加:
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" /><br />
2:CatType使用聚合函数,如count:
<asp:Button ID="Button2" runat="server" OnClick="Button2_Click" Text="Button" /><br />
3:CatType使用聚合函数,如max:
<asp:Button ID="Button3" runat="server" OnClick="Button3_Click" Text="Button" /><br /><br />
4:增加一只猫Cat,名为JACK:
<asp:Button ID="Button6" runat="server" OnClick="Button6_Click" Text="Button" /><br /><br />
5:增加一只猫Cat,名为TOM,种类为xianluo,同时为该猫增加一个伴侣,名为MARY,cat和catPart进行one-to-one映射:
<asp:Button ID="Button4" runat="server" OnClick="Button4_Click" Text="Button" /><br />
6:为名为jack的那只猫,增加一个伴侣rose:
<asp:Button ID="Button5" runat="server" OnClick="Button5_Click" Text="Button" /><br />
7:为名为jack的那只猫,增加2个演出计划CatTvPlan:
<asp:Button ID="Button7" runat="server" OnClick="Button7_Click" Text="Button" /><br />
8:增加猫john,同时增加1个演出计划CatTvPlan,2个穿衣方案CatDressScheme,3个食物方案CatFoodScheme:
<asp:Button ID="Button8" runat="server" OnClick="Button8_Click" Text="Button" /><br />
9:查询猫john,同时查出其所有的演出计划CatTvPlan,穿衣方案CatDressScheme,食物方案CatFoodScheme:
<asp:Button ID="Button9" runat="server" OnClick="Button9_Click" Text="Button" /><br />
10:只查询猫john,不同时查出其所有的演出计划CatTvPlan,穿衣方案CatDressScheme,食物方案CatFoodScheme:
(这里需要注意到是,只要不访问Cat类的LIST对象,如CatTvPlans,它就不会执行SELECT语句,也就是不会从数据库取值并赋值。)
但是,lazy="true" cascade="all-delete-orphan"
<asp:Button ID="Button10" runat="server" OnClick="Button10_Click" Text="Button" /><br />
11:将猫john改名为jordan
<asp:Button ID="Button11" runat="server" OnClick="Button11_Click" Text="Button" /><br />
12:将猫jordan的穿衣方案删除,一次删除一个
<asp:Button ID="Button12" runat="server" OnClick="Button12_Click" Text="Button" /><br />
13:将猫jordan的演出计划和食物方案全部删除
<asp:Button ID="Button13" runat="server" OnClick="Button13_Click" Text="Button" /><br />
</div>
2.5.2 业务代码
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using NHibernate;
using NHibernate.Cfg;
using Stclass.StEntity;
using NHibernate.Expression;
public partial class Example : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
/// <summary>
/// 增加一个猫的种类
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button1_Click(object sender, EventArgs e)
{
ISession session = Stclass.StEntity.NHibernateHelper.GetCurrentSession();
ITransaction tx = session.BeginTransaction();
CatType ct = new CatType();
ct.TypeName = "xianluo";
IQuery query = session.CreateQuery("select c from CatType as c where c.TypeName = :tname");
query.SetString("tname", "xianluo");
if (query.List().Count > 0)
{
Response.Write("haved xianluo");
return;
}
session.Save(ct);
tx.Commit();
Response.Write("id:" + ct.Id + "<br/>");
Response.Write("name:" + ct.TypeName + "<br/>");
NHibernateHelper.CloseSession();
}
/// <summary>
/// 增加一个猫Cat,名为JACK
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button6_Click(object sender, EventArgs e)
{
ISession session = Stclass.StEntity.NHibernateHelper.GetCurrentSession();
ITransaction tx = session.BeginTransaction();
Cat cat = new Cat();
cat.CatTypeID = 1;
cat.Name = "jack";
cat.Sex = "f";
cat.Weight = 27;
IQuery query = session.CreateQuery("select c from Cat as c where c.Name = :name");
query.SetString("name", "jack");
if (query.List().Count > 0)
{
Response.Write("haved jack");
return;
}
session.Save(cat);
tx.Commit();
Response.Write("id:" + cat.Id + "<br/>");
Response.Write("name:" + cat.Name + "<br/>");
NHibernateHelper.CloseSession();
}
/// <summary>
/// count
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button2_Click(object sender, EventArgs e)
{
ISession session = Stclass.StEntity.NHibernateHelper.GetCurrentSession();
ITransaction tx = session.BeginTransaction();
IQuery query2 = session.CreateQuery("select count(a) from CatType a");
IEnumerator itor = query2.Enumerable().GetEnumerator();
itor.MoveNext();
Response.Write("Female Cat: " + itor.Current.ToString() + "<br/>");
//Response.Write(((CatType)itor[0]).Id);
//tx.Commit();
}
/// <summary>
/// max
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button3_Click(object sender, EventArgs e)
{
ISession session = Stclass.StEntity.NHibernateHelper.GetCurrentSession();
ITransaction tx = session.BeginTransaction();
ISQLQuery query2 = session.CreateSQLQuery("select * from CatType").AddScalar("TypeName", NHibernateUtil.String);
IList itor = query2.List();
Response.Write("Female Cat: " + itor[1].ToString() + "<br/>");
IQuery query3 = session.CreateQuery("select max(a.Id) from CatType a");
query3.List();
itor = query3.List();
Response.Write("Female Cat: " + itor.Count + itor[0].ToString() + "<br/>");
query3 = session.CreateQuery("select avg(a.Id) from CatType a");
query3.List();
itor = query3.List();
Response.Write("Female Cat: " + itor.Count + itor[0].ToString() + "<br/>");
}
/// <summary>
/// 增加一只猫Cat,名为TOM,种类为xianluo,同时为该猫增加一个伴侣,名为MARY,cat和catPart进行one-to-one映射:
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button4_Click(object sender, EventArgs e)
{
ISession session = Stclass.StEntity.NHibernateHelper.GetCurrentSession();
ITransaction tx = null;
try
{
Cat cat = new Cat();
cat.CatTypeID = 1;
cat.Name = "TOM";
cat.Sex = "f";
cat.Weight = 27;
IQuery query = session.CreateQuery("select c from Cat as c where c.Name = :name");
query.SetString("name", "TOM");
if (query.List().Count > 0)
{
Response.Write("haved jack");
return;
}
tx=session.BeginTransaction();
CatPart cp = new CatPart();
cp.PartName = "MARY";
cp.Cat = cat;
session.Save(cat);
//因为one-to-one并不建议使用,故catpart增加了catid
cp.Id = cat.Id;
session.Save(cp);
tx.Commit();
cat = null;
cp = null;
}
catch (HibernateException ex)
{
if (tx != null) tx.Rollback();
throw ex;
}
finally
{
session.Close();
}
}
/// <summary>
/// 为名为jack的那只猫,增加一个伴侣rose
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button5_Click(object sender, EventArgs e)
{
ISession session = Stclass.StEntity.NHibernateHelper.GetCurrentSession();
ITransaction tx = null;
try
{
CatPart cp = new CatPart();
IQuery query = session.CreateQuery("select c from Cat as c where c.Name = :name");
query.SetString("name", "jack");
if (query.List().Count < 0)
{
Response.Write("have not added jack");
return;
}
query = session.CreateQuery("select c from CatPart as c where c.PartName = :name");
query.SetString("name", "rose");
if (query.List().Count > 0)
{
Response.Write("have added rose");
return;
}
IList il = query.List();
cp.Id = ((Cat)il[0]).Id;
cp.PartName = "rose";
tx = session.BeginTransaction();
session.Save(cp);
Cat cat = new Cat();
CatType catType = new CatType("temp");
catType.Id = 1;
string guidString = Guid.NewGuid().ToString("N");
guidString.Replace("-", "");
cat.Id = "536fb 62a 246745f 681868ba515d56afc";
cat.CatType = catType;
cat.Name = "jack";
cat.Sex = "F";
cat.Weight = 27;
CatTvPlan ctp = new CatTvPlan();
ctp.TvName = "ddddd";
//ctp.Cat = cat;
cat.CatTvPlans.Add(ctp);
//cat.CatTvPlans.Add(ctp2);
session.Save(ctp);
//session.Save(cartPart);
//Cat cat = session.Load(typeof(Cat), "536fb 62a 246745f 681868ba515d56afc") as Cat;
(Cat)session.Load(typeof(Cat), "536fb 62a 246745f 681868ba515d56afc");
//CatTvPlan ctp = new CatTvPlan();
//ctp.TvName = "xxx";
//ctp.Cat = cat;
cat.CatTvPlans.Add(ctp);
//session.Save(ctp);
Parent p = (Parent) session.load(Parent.class, pid);
Child c = new Child();
p.addChild(c);
session.save(c);
session.flush();
tx.Commit();
}
catch (HibernateException ex)
{
if (tx != null) tx.Rollback();
throw ex;
}
finally
{
session.Close();
}
}
/// <summary>
/// 为名为jack的那只猫,增加2个演出计划CatTvPlan:
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button7_Click(object sender, EventArgs e)
{
ISession session = Stclass.StEntity.NHibernateHelper.GetCurrentSession();
ITransaction tx = null;
try
{
IQuery query = session.CreateQuery("select c from Cat as c where c.Name = :name");
query.SetString("name", "jack");
if (query.List().Count < 0)
{
Response.Write("have not added jack");
return;
}
IList il = query.List();
Cat cat = (Cat)il[0];
tx = session.BeginTransaction();
CatTvPlan ctp1 = new CatTvPlan();
ctp1.Cat = cat;
ctp1.TvName = "sch 1";
CatTvPlan ctp2 = new CatTvPlan();
ctp2.Cat = cat;
ctp2.TvName = "sch 2";
session.Save(ctp1);
session.Save(ctp2);
tx.Commit();
cat = null;
ctp1 = null;
ctp2 = null;
}
catch (HibernateException ex)
{
if (tx != null) tx.Rollback();
throw ex;
}
finally
{
session.Close();
}
}
/// <summary>
/// 增加猫john,同时增加1个演出计划CatTvPlan,2个穿衣方案CatDressScheme,3个食物方案CatFoodScheme:
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button8_Click(object sender, EventArgs e)
{
ISession session = Stclass.StEntity.NHibernateHelper.GetCurrentSession();
ITransaction tx = null;
try
{
IQuery query = session.CreateQuery("select c from Cat as c where c.Name = :name");
query.SetString("name", "john");
if (query.List().Count > 0)
{
Response.Write("haved john");
return;
}
Cat cat = new Cat();
cat.CatTypeID = 1;
cat.Name = "john";
cat.Sex = "f";
cat.Weight = 33;
CatTvPlan ctp1 = new CatTvPlan();
ctp1.Cat = cat;
ctp1.TvName = "sch 1";
CatDressScheme cds1 = new CatDressScheme();
cds1.Cat = cat;
cds1.DsName = "cds 1";
CatDressScheme cds2 = new CatDressScheme();
cds2.Cat = cat;
cds2.DsName = "cds 2";
CatFoodScheme cfs1 = new CatFoodScheme();
cfs1.Cat = cat;
cfs1.ScName = "cfs1";
CatFoodScheme cfs2 = new CatFoodScheme();
cfs2.Cat = cat;
cfs2.ScName = "cfs2";
CatFoodScheme cfs3 = new CatFoodScheme();
cfs3.Cat = cat;
cfs3.ScName = "cfs3";
cat.CatTvPlans.Add(ctp1);
cat.CatDressSchemes.Add(cds1);
cat.CatDressSchemes.Add(cds2);
cat.CatFoodSchemes.Add(cfs1);
cat.CatFoodSchemes.Add(cfs2);
cat.CatFoodSchemes.Add(cfs3);
tx = session.BeginTransaction();
//session.Save(cat);
//session.SaveOrUpdate(cat);
session.SaveOrUpdateCopy(cat);
session.Flush();
tx.Commit();
cat = null;
//ctp1 = null;
//ctp2 = null;
}
catch (HibernateException ex)
{
if (tx != null) tx.Rollback();
throw ex;
}
finally
{
session.Close();
}
}
/// <summary>
/// 查询猫john,同时查出其所有的演出计划CatTvPlan,穿衣方案CatDressScheme,食物方案CatFoodScheme:
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button9_Click(object sender, EventArgs e)
{
ISession session = Stclass.StEntity.NHibernateHelper.GetCurrentSession();
try
{
IQuery query = session.CreateQuery("select c from Cat as c where c.Name = :name");
query.SetString("name", "john");
IList il = query.List();
if (il.Count > 0)
{
Response.Write("cat name:" + ((Cat)il[0]).Name + "<br/><br/>");
for (int i = 0; i < ((Cat)il[0]).CatTvPlans.Count; i++)
{
Response.Write("catTvPlan" + (i + 1) + ": " + ((CatTvPlan)((Cat)il[0]).CatTvPlans[i]).TvName + "<br/>") ;
}
for (int i = 0; i < ((Cat)il[0]).CatDressSchemes.Count; i++)
{
Response.Write("catDressScheme" + (i + 1) + ": " + ((CatDressScheme)((Cat)il[0]).CatDressSchemes[i]).DsName + "<br/>");
}
for (int i = 0; i < ((Cat)il[0]).CatFoodSchemes.Count; i++)
{
Response.Write("catFoodScheme" + (i + 1) + ": " + ((CatFoodScheme)((Cat)il[0]).CatFoodSchemes[i]).ScName + "<br/>");
}
}
}
catch (HibernateException ex)
{
throw ex;
}
finally
{
session.Close();
}
}
/// <summary>
/// 只查询猫john,不同时查出其所有的演出计划CatTvPlan,穿衣方案CatDressScheme,食物方案CatFoodScheme:
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button10_Click(object sender, EventArgs e)
{
Session.Clear() ;
ISession session = Stclass.StEntity.NHibernateHelper.GetCurrentSession();
try
{
//IQuery query = session.CreateQuery("from Cat as c where c.Name = :name");
//query.SetString("name", "john");
//IList il = query.List();
IList il = session.CreateCriteria(typeof(Cat)).Add(Expression.Eq("Name", "john"))
.SetFetchMode("CatFoodSchemes", FetchMode.Lazy)
.SetFetchMode("CatDressSchemes", FetchMode.Lazy)
.SetFetchMode("CatTvPlans", FetchMode.Lazy)
.List();
if (il.Count > 0)
{
Response.Write("cat name:" + ((Cat)il[0]).Name + "<br/><br/>");
//这里需要注意到是,只要不访问Cat类的LIST对象,如CatTvPlans,它就不会执行SELECT语句,也
//就是不会从数据库取值并赋值。
//for (int i = 0; i < ((Cat)il[0]).CatTvPlans.Count; i++)
//{
// Response.Write("catTvPlan" + (i + 1) + ": " + ((CatTvPlan)((Cat)il[0]).CatTvPlans[i]).TvName + "<br/>");
//}
//for (int i = 0; i < ((Cat)il[0]).CatDressSchemes.Count; i++)
//{
// Response.Write("catDressScheme" + (i + 1) + ": " + ((CatDressScheme)((Cat)il[0]).CatDressSchemes[i]).DsName + "<br/>");
//}
//for (int i = 0; i < ((Cat)il[0]).CatFoodSchemes.Count; i++)
//{
// Response.Write("catFoodScheme" + (i + 1) + ": " + ((CatFoodScheme)((Cat)il[0]).CatFoodSchemes[i]).ScName + "<br/>");
//}
// Response.Write( ((Cat)il[0]).CatPart.PartName );
}
}
catch (HibernateException ex)
{
throw ex;
}
finally
{
session.Close();
}
}
/// <summary>
/// 将猫john改名为jordan
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button11_Click(object sender, EventArgs e)
{
Session.Clear();
ISession session = Stclass.StEntity.NHibernateHelper.GetCurrentSession();
try
{
//IQuery query = session.CreateQuery("from Cat as c where c.Name = :name");
//query.SetString("name", "john");
//IList il = query.List();
IList il = session.CreateCriteria(typeof(Cat)).Add(Expression.Eq("Name", "john"))
.SetFetchMode("CatFoodSchemes", FetchMode.Lazy)
.SetFetchMode("CatDressSchemes", FetchMode.Lazy)
.SetFetchMode("CatTvPlans", FetchMode.Lazy)
.List();
Cat ct = null;
if (il.Count > 0)
{
ct = (Cat)il[0];
ct.Name = " jordan ";
}
ITransaction tx = session.BeginTransaction();
session.Update(ct);
tx.Commit();
NHibernateHelper.CloseSession();
}
catch (HibernateException ex)
{
throw ex;
}
finally
{
session.Close();
}
}
/// <summary>
/// 将猫jordan的穿衣方案删除,一次删除一个
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button12_Click(object sender, EventArgs e)
{
Session.Clear();
ISession session = Stclass.StEntity.NHibernateHelper.GetCurrentSession();
try
{
//IQuery query = session.CreateQuery("from Cat as c where c.Name = :name");
//query.SetString("name", "john");
//IList il = query.List();
IList il = session.CreateCriteria(typeof(Cat)).Add(Expression.Eq("Name", " jordan "))
.SetFetchMode("CatFoodSchemes", FetchMode.Lazy)
.SetFetchMode("CatDressSchemes", FetchMode.Lazy)
.SetFetchMode("CatTvPlans", FetchMode.Lazy)
.List();
if (il.Count < 0)
{
Response.Write("have no jordan ");
return;
}
//因为这边不需要直接加载对象,直接删除,故
//int cID = ((Cat)il[0]).Id;
//do del
//end do
//或者,采用NH来做,但是效率低,因为首先需加载对象,也就是先select
il = il = session.CreateCriteria(typeof(CatDressScheme)).Add(Expression.Eq("Cat", (Cat)il[0])).List();
if (il.Count < 1)
{
Response.Write(" jordan have no dressScheme");
return;
}
ITransaction tx = session.BeginTransaction();
session.Delete((CatDressScheme)il[0]);
tx.Commit();
NHibernateHelper.CloseSession();
}
catch (HibernateException ex)
{
throw ex;
}
finally
{
session.Close();
}
}
/// <summary>
/// 将猫jordan的演出计划和食物方案全部删除
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button13_Click(object sender, EventArgs e)
{
Session.Clear();
ISession session = Stclass.StEntity.NHibernateHelper.GetCurrentSession();
try
{
//IQuery query = session.CreateQuery("from Cat as c where c.Name = :name");
//query.SetString("name", "john");
//IList il = query.List();
IList il = session.CreateCriteria(typeof(Cat)).Add(Expression.Eq("Name", " jordan "))
.SetFetchMode("CatFoodSchemes", FetchMode.Lazy)
.SetFetchMode("CatDressSchemes", FetchMode.Lazy)
.SetFetchMode("CatTvPlans", FetchMode.Lazy)
.List();
if (il.Count < 0)
{
Response.Write("have no jordan ");
return;
}
ITransaction tx = session.BeginTransaction();
session.Delete((Cat)il[0]);
tx.Commit();
NHibernateHelper.CloseSession();
}
catch (HibernateException ex)
{
throw ex;
}
finally
{
session.Close();
}
}
}
2.6使用聚合等函数
HQL支持以下的聚合函数:
1. avg(…), sum(…)
2. min(…), max(…)
3. count(*), count(…), count(distinct…), count(all…)
示例一:
IQuery query2 = session.CreateQuery("select count(a) from CatType a");
IEnumerator itor = query2.Enumerable().GetEnumerator();
itor.MoveNext();
Response.Write("Female Cat: " + itor.Current.ToString() + "<br/>");
示例二:
IQuery query3 = session.CreateQuery("select max(a.Id) from CatType a");
query3.List();
itor = query3.List();
Response.Write("Female Cat: " + itor.Count + itor[0].ToString() + "<br/>");
query3 = session.CreateQuery("select avg(a.Id) from CatType a");
query3.List();
itor = query3.List();
Response.Write("Female Cat: " + itor.Count + itor[0].ToString() + "<br/>");
2.6取得单个字段
ISQLQuery query2 = session.CreateSQLQuery("select * from CatType").AddScalar("TypeName", NHibernateUtil.String);
IList itor = query2.List();
Response.Write("Female Cat: " + itor[1].ToString() + "<br/>");
虽然可以如上取得,但是这样子就失去了NH作为持久化层的作用。
2.6直接执行SQL和存储过程
在有些时候,可能需要直接执行SQL语句、存储过程等,但nhibernate并没有提供一种让我们执行SQL语句的方法,不过可以通过一些间接的方法来实现。
1. IDriver接口
IDriver接口就是数据访问的驱动器,对于不同的数据提供者(SqlClient, OleDb等)就有不同的驱动器,与SqlClient对应的是SqlClientDriver, 而与OleDb对应的就是OleDbDriver。
IDriver接口用于取得连接对象,命令对象,并且格式化命令文本。
2. 取得数据库连接对象
要执行SQL,必须取得IDbConnection对象,它可以通过会话工厂取得。要注意的是ISessionFactory接口并没有提供与连接对象相关的操作,这些操作由ISessionFactoryImplementor接口定义。
ISessionFactoryImplementor继承自ISessionFactory,而会话工厂的实现类SessionFactoryImpl实现了这两个接口。
取得连接对象的代码如下:
ISessionFactoryImplementor factory = (ISessionFactoryImplementor)cfg.BuildSessionFactory();
IDbConnection conn = factory.OpenConnection();
OpenConnection方法从连接提供者ConnectionProvider取得IDbConnection对象,而连接提供者通过Driver对象创建IDbConnection。
3. 获得IDbCommand对象
在nhibernate内部,数据操作都是通过IDbCommand对象完成的,使用Command对象可以防止注入式攻击和处理一些特殊字符。
取得IDbCommand对象的代码下:
IDbCommand cmd = factory.ConnectionProvider.Driver.CreateCommand();
可能有人会问,直接new SqlCommand()不就可以啦(如果使用SqlClient的话里有话),干吗这么复杂?
没错,这样确实是可以的,nhibernate内部也是这样做的。但如果我们直接这样做的话,那代码就没有很好的移植性,如果改变数据库连接方式,那么就需要更改代码了,而使用上面的代码则不需求更改任何代码。当然,SQL语句除外。
至于参数,通过IDbCommand.CreateParameter就可以处理了,这里就不多说了。
4. 示例
下面给出一个在nhibernate中执行SQL语句的方法ExecuteSQL。
public IList ExecuteSQL( string query ) {
IList result = new ArrayList();
ISessionFactoryImplementor s = (ISessionFactoryImplementor)cfg.BuildSessionFactory();
IDbCommand cmd = s.ConnectionProvider.Driver.CreateCommand();
cmd.CommandText = query;
IDbConnection conn = s.OpenConnection();
try {
cmd.Connection = conn;
IDataReader rs = cmd.ExecuteReader();
while ( rs.Read() ) {
int fieldCount = rs.FieldCount;
object[] values = new Object[ fieldCount ];
for ( int i = 0; i < fieldCount; i ++ )
values[i] = rs.GetValue(i);
result.Add( values );
}
}
finally {
s.CloseConnection(conn);
}
return result;
}
执行存储过程的方法. public IList ExecuteStoredProc( string spName, ICollection paramInfos ) {
IList result = new ArrayList();
ISessionFactoryImplementor s = (ISessionFactoryImplementor)cfg.BuildSessionFactory();
IDbCommand cmd = s.ConnectionProvider.Driver.CreateCommand();
cmd.CommandText = spName;
cmd.CommandType = CommandType.StoredProcedure;
// 加入参数
if ( paramInfos != null ) {
foreach( ParamInfo info in paramInfos ) {
IDbDataParameter parameter = cmd.CreateParameter();
parameter.ParameterName = info.name; // driver.FormatNameForSql( info.Name );
parameter.Value = info.Value;
cmd.Parameters.Add( parameter );
}
}
IDbConnection conn = s.OpenConnection();
try {
cmd.Connection = conn;
IDataReader rs = cmd.ExecuteReader();
while ( rs.Read() ) {
int fieldCount = rs.FieldCount;
object[] values = new Object[ fieldCount ];
for ( int i = 0; i < fieldCount; i ++ )
values[i] = rs.GetValue(i);
result.Add( values );
}
}
finally {
s.CloseConnection(conn);
}
return result;
} 其中ParamInfo为存储参数信息的结构, 定义如下:
public struct ParamInfo {
public string Name;
public object Value;
}
返回结果与nhibernate的query的结果保存一致(返回object[]的情况)。