2011-03-28 183 views
5

我有一个很大且复杂的SQL查询,它带有一个在NHibernate中运行的DISTINCT子句(这是一个包含各种条件和连接的搜索查询)。但我在使用SQL Server 2008中的分页时遇到问题。如何使用DISTINCT在NHibernate SQL查询中执行分页

我的问题是:我如何从NHibernate执行此操作,而不是使用手动解决方法(下面概述)?

我正在使用的代码是这样的:

var searchQuery = BuildQuery(criteria); 
    .SetTimeout(240) 
    .SetFirstResult(pageIndex * pageSize) 
    .SetMaxResults(pageSize); 
var resultRows = searchQuery.List<object[]>(); 

我的SQL查询的结果(从BuildQuery对于(),无DISTINCT)看起来就像这样(高度简化):

Id, Name, SortColumn 
1 AA 1/1/2000 
1 AA 1/1/2000 
2 AB 3/1/2000 
2 AB 3/1/2000 
3 AC 10/1/2000 
3 AC 10/1/2000 
.... 

由于查询的工作方式,我无法避免重复行,所以我在SQL查询中附加了一个DISTINCT以使它们消失。

要做到分页,NHibernate的生成这样的查询(本例中为每页100个结果的第二页):

SELECT TOP 100 Id, 
      Name, 
      SortColumn, 
FROM  (select distinct Id, Name, SortColumn, 
       ROW_NUMBER() OVER (ORDER BY SortColumn) as __hibernate_sort_row 
      from ...... 
      where ......) as query 
WHERE query.__hibernate_sort_row > 100 
ORDER BY query.__hibernate_sort_row 

也能正常工作的第一页,但在随后的页面我只获得预期成果的一半。

我运行SQL NHibernate的子查询中,发现NHibernate的插入做它的分页行返回意想不到的事情(即使是不同的):

Id, Name, SortColumn,  __hibernate_sort_row 
1 AA 1/1/2000,  1 
1 AA 1/1/2000,  2 
2 AB 3/1/2000,  3 
2 AB 3/1/2000,  4 
3 AC 10/1/2000,  5 
3 AC 10/1/2000,  6 
.... 

当NHibernate的包装此在子查询中对__hibernate_sort_row过滤列,它返回100行,但因为每一行都是重复的,所以我的页面上只有50行。这是因为DISTINCT没有像我期望的那样合并行。 (所有这些都回到了SQL 2008中ROW_NUMBER()函数如何在DISTINCT子句中工作,但这是NHibernate的问题,而不是我的)。

SELECT TOP 100 paginationOuter.* 
FROM 
(
SELECT paginationInner.* 
    ,ROW_NUMBER() OVER(ORDER BY SortColumn ASC) AS RowNum 
FROM 
    (
      select distinct Id, Name, SortColumn, 
      from ...... 
      where ...... 
    ) AS paginationInner 
) AS paginationOuter 
WHERE paginationOuter.RowNum > 100 
ORDER BY paginationOuter.RowNum 

我的问题是:我怎么做到这一点从NHibernate的,而不是我手动解决方法

我通过包裹在两个子查询的查询和人工处理分页目前解决这个问题呢?

我正在使用NHibernate版本2.1.2。

不幸的是,我无法将此查询转换为HQL或LINQ(除非有人可以提供给我几周​​的空闲时间!)。我也不能从查询中删除DISTINCT。

+0

看起来像你的解决方案是非常做到这一点的唯一途径。 http://julianjelfs.wordpress.com/2009/04/03/nhibernate-removing-duplicates-combined-with-paging/ – Vadim 2011-03-28 15:26:29

+0

@Vadim - 我担心会是这样。你可以把你的评论作为答案,我会将其标记为已接受。 – ligos 2011-03-28 21:59:38

回答