NHibernate.3.0.Cookbook第四章第2节的翻译

Using Criteria Queries

使用条件查询

  在上一章中,通过实体的ID来获取这些实体.本节介绍几个基础的条件查询:通过实体的属性来获取实体.

步骤

1.   完成本章简介中的通用步骤.
2.   在Queries类中,添加下面的方法:

View Code
public IEnumerable<Movie> GetMoviesDirectedBy(string directorName)
{
  return _session.CreateCriteria<Movie>()
    .Add(Restrictions.Eq("Director", directorName))
    .List<Movie>();
}

3.   在Queries类中,添加下面的方法,该方法通过actor name来查询movies:

View Code
public IEnumerable<Movie> GetMoviesWith(string actorName)
{
  return _session.CreateCriteria<Movie>()
    .CreateCriteria("Actors", JoinType.InnerJoin)
    .Add(Restrictions.Eq("Actor", actorName))
    .List<Movie>();
}

4.   在Queries类中,添加下面的方法,该方法通过ISBN来查询book:

View Code
public Book GetBookByISBN(string isbn)
{
  return _session.CreateCriteria<Book>()
    .Add(Restrictions.Eq("ISBN", isbn))
    .UniqueResult<Book>();
}

5.   添加下面的方法,该方法查找一定价格范围内的所有产品:

View Code
public IEnumerable<Product> GetProductByPrice(
  decimal minPrice,
  decimal maxPrice)
{
  return _session.CreateCriteria<Product>()
    .Add(Restrictions.And(
      Restrictions.Ge("UnitPrice", minPrice),
      Restrictions.Le("UnitPrice", maxPrice)
           ))
    .AddOrder(Order.Asc("UnitPrice"))
    .List<Product>();
}

6.   在Program.cs中, 为RunQueries方法添加下述代码:

View Code
static void RunQueries(ISession session)
{
  var queries = new Queries(session);
  Show("Movies directed by Spielberg:",
    queries.GetMoviesDirectedBy(
    "Steven Spielberg"));
  Show("Movies with Morgan Freeman:",
    queries.GetMoviesWith(
    "Morgan Freeman"));
  Show("This book:",
    queries.GetBookByISBN(
    "978-1-849513-04-3"));
  Show("Cheap products:",
    queries.GetProductByPrice(0M, 15M));
}

7.   编译运行,结果如下图所示:

原理

  让我们来逐一地来查看这四个查询:

  • GetMoviesDirectedBy 查询
View Code
_session.CreateCriteria<Movie>()
        .Add(Restrictions.Eq("Director", directorName))
        .List<Movie>();

  上面的代码中,使用session.CreateCriteria获得了一个ICriteria对象.泛型参数Movie告诉NHibernate即将在movies上进行查询.代码第二行,movies约束条件为:由Steven Spielberg执导.最后,调用List方法,该方法执行查询并返回由Steven Spielberg执导的movies.由于泛型参数Movie,NHibernate返回了一个强类型IList<Movie>,而不是IList.
  在Microsoft SQL Server中, 生成的SQL语句如下:

View Code
SELECT   this_.Id          as Id1_0_,
         this_.Name        as Name1_0_,
         this_.Description as Descript4_1_0_,
         this_.UnitPrice   as UnitPrice1_0_,
         this_.Director    as Director1_0_
FROM     Product this_
WHERE    this_.ProductType = 'Eg.Core.Movie'
         AND this_.Director = 'Steven Spielberg' /* @p0 */
  • GetMoviesWith 查询
View Code
_session.CreateCriteria<Movie>()
        .CreateCriteria("Actors", JoinType.InnerJoin)
        .Add(Restrictions.Eq("Actor", actorName))
        .List<Movie>();

  我们再一次对movies进行查询,但是在这个示例中,我们基于一个子集合来进行查询.我们想得到Morgan Freeman的所有movies.依据我们的模型,返回所有对应的ActorRole对象中Actor为Morgan Freeman的movies.
  代码第二行,基于Movie的Actors集合,在Movies和ActorRoles上设置了一个inner join查询.在SQL中inner join查询只返回匹配的行.CreateCriteria可以改变从Movie到ActorRole的查询结果,这使得我们可以进一步筛选ActorRoles(在代码第三行) .
  代码第三行,我们只是筛选ActorRole对象,直至只有Morgan Freeman的角色.由于是inner join查询,同样也会筛选Movies.最后执行该查询并调用List<Movie>得到结果.
  在Microsoft SQL Server中, 生成的SQL语句如下:

View Code
SELECT this_.Id            as Id1_1_,
       this_.Version       as Version1_1_,
       this_.Name          as Name1_1_,
       this_.Description   as Descript5_1_1_,
       this_.UnitPrice     as UnitPrice1_1_,
       this_.Director      as Director1_1_,
       actorrole1_.Id      as Id0_0_,
       actorrole1_.Version as Version0_0_,
       actorrole1_.Actor   as Actor0_0_,
       actorrole1_.Role    as Role0_0_
FROM   Product this_
       inner join ActorRole actorrole1_
         on this_.Id = actorrole1_.MovieId
WHERE  this_.ProductType = 'Eg.Core.Movie'
       AND actorrole1_.Actor = 'Morgan Freeman' /* @p0 */
  • GetBookByISBN 查询
View Code
_session.CreateCriteria<Book>()
        .Add(Restrictions.Eq("ISBN", isbn))
        .UniqueResult<Book>();

  在这个条件查询中,通过ISBN来查询特定的book.由于使用UniqueResult<Book>替代了List<Book>,NHibernate将返回一个单独的Book对象,如果查询结果为空,将返回null.该查询假的ISBN是唯一的.
  在Microsoft SQL Server中, 生成的SQL语句如下:

View Code
SELECT this_.Id          as Id1_0_,
       this_.Name        as Name1_0_,
       this_.Description as Descript4_1_0_,
       this_.UnitPrice   as UnitPrice1_0_,
       this_.Author      as Author1_0_,
       this_.ISBN        as ISBN1_0_
FROM   Product this_
WHERE  this_.ProductType = 'Eg.Core.Book'
       AND this_.ISBN = '3043' /* @p0 */
  • GetProductByPrice 查询
View Code
_session.CreateCriteria<Product>()
        .Add(Restrictions.And(
          Restrictions.Ge("UnitPrice", minPrice),
          Restrictions.Le("UnitPrice", maxPrice)
               ))
        .AddOrder(Order.Asc("UnitPrice"))
        .List<Product>()

  使用这个条件查询,使用一个And操作符将大于等于操作和小于等于操作结合起来,以返回在定价在两个值之间的产品.And约束需要两个子约束作为参数.也可以使用Between约束来达到相同的目的,代码如下:

.Add(Restrictions.Between("UnitPrice", minPrice, maxPrice))

  使用AddOrder方法,按照单价对product结果进行升序排序.
  在Microsoft SQL Server中, 生成的SQL语句如下:

 

View Code
SELECT   this_.Id          as Id1_0_,
         this_.Name        as Name1_0_,
         this_.Description as Descript4_1_0_,
         this_.UnitPrice   as UnitPrice1_0_,
         this_.Director    as Director1_0_,
         this_.Author      as Author1_0_,
         this_.ISBN        as ISBN1_0_,
         this_.ProductType as ProductT2_1_0_

     FROM     Product this_
WHERE    (this_.UnitPrice >= 0 /* @p0 */
          and this_.UnitPrice <= 15 /* @p1 */)
ORDER BY this_.UnitPrice asc

扩展

  这些条件API是为了动态的创建查询,就像我们在许多零售网站上看到的高级搜索功能.这些网站上,用户可以选择任意数量的筛选和排序条件.然而,这些查询必须动态解析和编译.
  相对于使用一组参数的静态查询,使用命名HQL查询将更好,因为她会在我们创建会话工厂的时候预编译
  这些条件API存在"魔法字符串"的问题,在这些字符串涉及到程序中属性和类的地方.通过使用Visual Studio的重构工具或者ReSharper,我们可以使用强类型来轻松改变属性的名字. 使用这些条件API时,如果我们变更了模型中的一个属性名,那我们将必须更新所有使用该属性的所有条件查询.但是,在下一小节中,新的QueryOver API将解决该问题.

转载于:https://www.cnblogs.com/carfieldSE/archive/2012/07/25/2606819.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值