NHibernate是使用ISession对象实现对数据库的增、删、改、查工作的。
一、对数据库的查询:NHibernate对数据库的查询可以使用四种方式来实现:
使用ISession对象的方法来实现查询
使用HQL语句来实现查询
使用Criteria实现查询
使用原始SQL语句来实现查询
1、使用ISession对象的Get()方法来根据主键查询对象
语法:T ISession.Get<T>(object Id)
通常使用这种方法来根据主键Id值来查询对象的,并返回查询到的实体对象。
2、使用HQL语句来实现查询。
为了实现对对象的灵活操作,NHibernate也引入了Hibernate查询语言(HQL,NHibernate Query Language),这种语句与SQL语句很像,但它是基于面向对象查询语言。它实际上是用OOP中的对象和属性映射了数据库中的表和列。
例如这一句:select c.Firstname from Customer c
Customer是一个对象,Firstname是Customer对象的属性。
在这里主要讨论一下from子句,select子句,where子句,order by子句,group by子句几个常用的子句。
from子句:
如“from Fruit”:就是取出Fruit实体类所映射的表的所有记录。还可以加上别名“from Fruit as f”。
public IList<Fruit> Select()
{
IList<Fruit> list = _Session.CreateQuery("from Fruit").List<Fruit>();
return list;
}
这里返回的是Fruit实体对象的集合。
select子句:
用来指定要从实体类所对应的表中检索出哪些属性。
public IList<object[]> SelectAll()
{
IList<object[]> list = _Session.CreateQuery("select f.Id,f.Name,f.Price from Fruit as f ").List<object[]>();
return list;
}
由于只是查询了有限的列出来,所以返回的不是实体对象的集合,而是object[]数组的集合。只要在select子句中指定多列,就不能返回实体对象的集合,而是返回object[]的集合。
另外需要注意的是:HQL语句中实体类的名子和属性的名子大小写敏感。
下面的代码是只查询不重复的Stack属性值的集合,由于查询结果只有一列,所以返回一个字符串的集合就可以了。
public IList<string> GetStacks()
{
IList<string> list = _Session.CreateQuery("select distinct f.Stack from Fruit as f").List<string>();
return list;
}
where子句:
用来从实体类对应的表中筛选出指定的对象集合。我们所知道的where中的and、or、not、is、like、between、in、>、<、=等等都可以直接拿来使用,
如:
select p.Name from Person p where p.Age > 20
from Person p where p.Age between 20 and 30
from person p where p.Age in (20,30)
from person p where p.Name is null
from person p where p.Name like 'Jaki%'
那如何在where子句中使用参数呢?比如我们要做一个登录,需要根据用户名和密码查询,那我们的HQL语句应当使用变量参数,变量参数以":参数名"的形式表示
from Login as login where login.Id=:u and login.Password=:p
那我们如何给:u和:p赋值呢?我们可以使用IQuery的SetXXX()方法(SetString(),SetBoolean(),SetInt32()......)来为参数赋值
下面是我们登录的代码段:
public bool Select(string uid, string pwd)
{
//写法1
//IList<Login> list = _Session.CreateQuery("from Login as login where login.Id='"+uid+"' and login.Password='"+pwd+"'").List<Login>();
//写法2
//IList<Login> list = _Session.CreateQuery("from Login as login where login.Id=? and login.Password=?").SetString(0,uid).SetString(1,pwd).List<Login>();
//写法3
IList<Login> list = _Session.CreateQuery("from Login as login where login.Id=:u and login.Password=:p").SetString("u",uid).SetString("p",pwd).List<Login>();
return list.Count > 0 ? true : false;
}
书写HQL参数有四种写法:
写法1:可能会引起SQL注入,不要使用。
写法2:ADO.NET风格的?参数,NHibernate的参数从0开始计数。
写法3:命名参数用:name的形式在查询字符串中表示,这时IQuery接口把实际参数绑定到命名参数。
写法4:命名的参数列表,把一些参数添加到一个集合列表中的形式,比如可以查询数据是否在这个集合列表中。
order by子句与group by 子句与SQL语法很像,在此不多说了,代码如下。
public IList<Customer> Orderby()
{
return _session.CreateQuery("select from Customer c order by c.Firstname asc,c.Lastname desc").List<Customer>();
}
public IList<object[]> Groupby()
{
return _session.CreateQuery("select c.Firstname, count(c.Firstname) from Customer c group by c.Firstname").List<object[]>();
}
3.使用Criteria实现查询
虽然HQL功能强大,但在程序中嵌入字符串给人的感觉不是很舒服,那我们还可以采用Criteria查询,Criteria是通过一组条件表达式(expression_r)来加载数据的,它返回满足条件的对象集合。
主要接口为ICriteria,nhibernate在session对象中为我们提供了一个方法CreateCriteria,此方法返回ICriteria接口。
下面我们看一下如何使用Criteria查询
public IList<Fruit> Select()
{
//生成ICriteria引用实例
ICriteria crit = _Session.CreateCriteria(typeof(Fruit));
//按照Price字段升序排列
crit.AddOrder(new NHibernate.Criterion.Order("Price", true));
//添加价格在1-5元之间的查询条件
crit.Add(Restrictions.Between("Price", 1, 5));
//添加货架在1,3,5,2货架的查询条件
crit.Add(Restrictions.In("Stack", new string[] { "1", "3", "5", "2" }));
//从第6条记录开始查询
crit.SetFirstResult(6);
//每次查询出来的最多记录条数
crit.SetMaxResults(2);
//返回泛型集合
IList<Fruit> list = crit.List<Fruit>();
return list;
}
主要方法:
SetMaxResults:设置返回的最大结果数,可用于分页;
SetFirstResult:设置首个对象返回的位置,可用于分页;
Add:加入条件表达式(expression_r对象),此方法可多次调用以组合多个条件;
AddOrder:加入排序的字段(Order对象);
List:返回满足条件的对象集合。
expression_r是一个abstract(抽象)类,它通过一组static方法实现Factory Method(工厂方法)模式,这些static方法返回的都是expression_r类的子类,下面列出一些常用的:
Eq:这是一个相等判断的表达式;
Like:这是一个like判断的表达式;
Gt:这是一个大于判断的表达式;
And:这是两个表达式And操作后的表达式;
Or:这是两个表达式Or操作后的表达式;
Between:这是一个范围筛选的条件表达式,在两个数之间的范围。
In:这也是一个范围筛选的条件表达式,在多个离散的值中进行筛选。
下面以几个例子来说明Criteria数据加载的用法:
1. 取得用户名(username)为billy的用户对象:
expression_r ex = expression_r.Eq( "Username", "billy" );
IList users = session.CreateCriteria(typeof(User)).Add( ex ).List();
2.取得用户名(username)为billy, 密码为123456的用户对象
expression_r ex = expression_r.And( expression_r.Eq("Username", "billy"),
expression_r.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.新建对象;
2.调用ISession.Save();
3.调用Flush()同步到数据库。
public void Insert(Fruit fruit)
{
_Session.Save(fruit);
_Session.Flush();
}
三、修改记录
1.获取对象;
2.修改它的一些属性;
3.调用ISession.Update();
4.调用Flush同步到数据库。
public void Update(Fruit fruit)
{
_Session.Update(fruit);
_Session.Flush();
}
四、删除记录
1.获取要删除的对象;
2.调用ISession.Delete();
3.调用Flush同步到数据库。
public void Delete(Fruit fruit)
{
_Session.Delete(fruit);
_Session.Flush();
}