迷恋弦哥

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Using MultiCriteria

使用多条件(MultiCriteria)

  为了显示大量的表单和web页面,我们需要运行好几个查询. 例如,将查询结果一次显示在一个页面里是很正常的,这通常需要两个查询.第一个统计所有有效的结果,第二个,只获取10个/20个结果的数据.MultiCriteria使得我们可以将这两个查询整合到一次数据库交互,以提高应用程序的性能.本节介绍如何使用MultiCriteria去获取products的一个分页的结果集.

准备

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

View Code
public struct PageOf<T>
{
  public int PageCount;
  public int PageNumber;
  public IEnumerable<T> PageOfResults;
}

3.   在Queries类中,添加下面的方法:

View Code
public PageOf<Product> GetPageOfProducts(
  int pageNumber,
  int pageSize)
{
  var skip = (pageNumber - 1) * pageSize;
  var countQuery = GetCountQuery();
  var resultQuery = GetPageQuery(skip, pageSize);
  var multiCrit = _session.CreateMultiCriteria()
    .Add<int>("count", countQuery)
    .Add<Product>("page", resultQuery);
  var productCount = ((IList<int>)multiCrit
    .GetResult("count")).Single();
  var products = (IList<Product>)multiCrit
    .GetResult("page");
  var pageCount = (int) Math.Ceiling(
    productCount/(double) pageSize);
  return new PageOf<Product>()
           {
             PageCount = pageCount,
             PageOfResults = products,
             PageNumber = pageNumber
           };
}
private ICriteria GetCountQuery()
{
  return _session.QueryOver<Product>()
    .Select(list => list
            .SelectCount(m => m.Id))
    .UnderlyingCriteria;
}
private ICriteria GetPageQuery(int skip, int take)
{
  return _session.QueryOver<Product>()
    .OrderBy(m => m.UnitPrice).Asc
    .Skip(skip)
    .Take(take)
    .UnderlyingCriteria;
}

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

View Code
static void RunQueries(ISession session)
{
  var queries = new Queries(session);
  var result = queries.GetPageOfProducts(1, 2);
  var heading = string.Format("Page {0} of {1}",
                              result.PageNumber,
                              result.PageCount);
  Show(heading, result.PageOfResults);
}

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

原理

  MultiCriteria API在所有NHibernate支持的RDBMS上都可以使用.但是,只有在Microsoft SQL Server和Oracle可以将两个查询整合到一次数据库交互中.而对于其他的数据库,该功能是模拟实现的.你的应用程序不必关注这个,总之,可以正常使用她.
  在本示例中,我们将两个查询整合到一次数据库交互中.我们的第一个查询,统计了数据库中所有的products,第二个查询,返回了一个页面,该页面含有三个products中的前两个,并按单价排序.我们使用QueryOver的Skip和Take实现该功能.
  在MultiCriteria语法中,有几个挺有意思的东西.
var multiCrit = session.CreateMultiCriteria()
  .Add<int>("count", countQuery)
  .Add<Movie>("page", resultQuery);
  首先, 你会注意到我们使用"count"和"page"标记了我们的查询.这不是必须的.相反,我们可以使用MultiCriteria中每个criteria对象的索引来获取结果.与列表索引相比,名字更不容易被搞乱,所以我们将使用名字.
  我们使用泛型参数来为我们的结果指明元素类型.也就是说,我们的第一个查询返回一个整数list,第二个返回一个movies的list.MultiCriteria没有提供一个方法来直接返回一个单一的实体或标量值.相反,我们使用LINQ to Object's的Single方法来获取list中的第一个也是唯一的一个值.
  当我们获得了product的计数时,两个查询都会被立即执行,并且结果被存储到内存中.当我们获得product的页面时,MultiCriteria 只返回已执行的查询的结果.

posted on 2012-07-25 14:49  迷恋弦哥  阅读(304)  评论(1)    收藏  举报