本节内容
上一节,我们介绍了NHibernate查询语言的一种:NHibernate查询语言(HQL,NHibernate Query Language),这一节介绍一下条件查询(Criteria API)。
在NHibernate中提供了三种查询方式给我们选择:NHibernate查询语言(HQL,NHibernate Query Language)、条件查询(Criteria API,Criteria Query)、(根据示例查询(QBE,Query By Example)是条件查询的一种特殊情况)、原生SQL(Literal SQL,T-SQL、PL/SQL)。每个人有不同的喜好和特长,可以根据自己的情况选择使用其中的一种或几种。这一节我们介绍条件查询。
HQL极为强大,但是有些人希望能够动态的使用一种面向对象API创建查询,而不是在.NET代码中嵌入字符串。在NHibernate中,提供了一种直观的、可扩展的Criteria API。在我们键入查询语句的时候,提供了编译时的语法检查,VS提供了强大的智能提示。如果你对HQL的语法感觉不是很舒服的话,用这种方法可能更容易。这种API也比HQL更可扩展。
典型用法:从ISession接口中创建ICriteria实例对象;在这个ICriteria实例对象上设置一个或多个表达式;要求ICriteria接口返回需要的列表,就是根据表达式从数据库中返回对象。
注意:由于篇幅有限,我在这里仅仅贴出了数据访问层的代码。测试这些方法的代码就没有贴出来了,你可以下载本系列的源代码仔细看看测试这些方法的代码。这些实例我争取写出来可以运行起来,大家下载源码看看效果,一些数据需要按个人数据库里的数据情况修改。例如查询条件和结果。这节,我们在上一节源代码的基础上,在数据访问层中新建QueryCriteriaAPI.cs类用于编写条件查询方法,在数据访问的测试层新建一QueryCriteriaAPIFixture.cs类用于测试。
使用ISession接口的CreateCriteria方法创建了NHibernate.ICriteria接口一个特定的持久化类的查询实例,也可以说ISession是用来制造Criteria实例的工厂。
public IList<Customer> CreateCriteria() { ICriteria crit = _session.CreateCriteria(typeof(Customer)); crit.SetMaxResults(50); IList<Customer> customers = crit.List<Customer>(); return customers; }
例如上面的例子返回Customer对象集合,设置最大的集合数量为50条。
使用ICriteria接口提供的Add方法添加Restrictions类中约束表达式可以限制一些结果集的作用。
public IList<Customer> Narrowing() { IList<Customer> customers = _session.CreateCriteria(typeof(Customer)) .Add(Restrictions.Like("Firstname", "YJing%")) .Add(Restrictions.Between("Lastname", "A%", "Y%")) .List<Customer>(); return customers; }
使用ICriteria.Order对结果集排序,第二个参数true代表asc,false代表desc。例如下面例子查询Customer对象按FirstName降序、Lastname升序。
public IList<Customer> Order() { return _session.CreateCriteria(typeof(Customer)) .Add(Restrictions.Like("Firstname","Y%")) .AddOrder(new NHibernate.Criterion.Order("Firstname", false)) .AddOrder(new NHibernate.Criterion.Order("Lastname", true)) .List<Customer>(); }
条件查询同样支持关联查询、动态关联抓取(在介绍一对多,多对多关系中阐述),投影、聚合和分组,离线(detached)查询和子查询是2.0版新增加的内容,以后在相关知识中介绍。也可以自行参考NHibernate参考文档13章。
根据示例查询(QBE,Query By Example)是条件查询的一种特殊情况,NHibernate.Criterion.Example类根据你指定的实例创造查询条件。其典型的用法:创建一个Example实例;在Example实例上设置值;根据Example和设置NHibernate返回其对象集合。
例如下面的例子,按照指定Customer查询数据库里的记录:
public IList<Customer> Query() { Customer customerSample = new Customer() { Firstname = "YJing", Lastname = "Lee" }; return _session.CreateCriteria(typeof(Customer)) .Add(Example.Create(customerSample)) .List<Customer>(); }
你可以自行调整Example使之更实用:
public IList<Customer> UseQueryByExample_GetCustomer(Customer customerSample) { Example example = Example.Create(customerSample) .IgnoreCase() .EnableLike() .SetEscapeCharacter('&'); return _session.CreateCriteria(typeof(Customer)) .Add(example) .List<Customer>(); }
实例1:利用CriteriaAPI按Firstname和Lastname查询顾客。
public IList<Customer> GetCustomersByFirstnameAndLastname(string firstname, string lastname) { return _session.CreateCriteria(typeof(Customer)) .Add(Restrictions.Eq("Firstname", firstname)) .Add(Restrictions.Eq("Lastname", lastname)) .List<Customer>(); }
测试:调用GetCustomersByFirstnameAndLastname方法,查询Firstname为“YJing",Lastname为"Lee"的顾客,判断查询结果数量是否为1。(注:在数据库中有符合这一个记录)
[Test] public void GetCustomerByFirstnameAndLastnameTest() { IList<Customer> customers = _queryCriteriaAPI.GetCustomersByFirstnameAndLastname("YJing", "Lee"); Assert.AreEqual(1, customers.Count); }
实例2:利用CriteriaAPI获取顾客ID大于CustomerId的顾客。
public IList<Customer> GetCutomersWithIdGreaterThan(int customerId) { return _session.CreateCriteria(typeof(Customer)) .Add(Restrictions.Gt("CustomerId", customerId)) .List<Customer>(); }
好了,通过2篇文章的介绍,对NHibernate中的查询语法有了大致了解,知道了NHibernate中两种最主要的查询方式,还有一种原生SQL查询,内容不多,请参考NHibernate官方文档吧。多多练习!下节将介绍对对象的操作。