2011-03-28 12 views
5

Tengo una consulta SQL grande y complicada con una cláusula DISTINCT que se ejecuta en NHibernate (es una consulta de búsqueda con una gran variedad de criterios y combinaciones). Pero estoy teniendo un problema al usar la paginación con SQL Server 2008.Cómo hacer la paginación en una consulta NHibernate SQL con DISTINCT

Mi pregunta es: ¿cómo puedo hacer esto desde NHibernate y no con mi solución manual (que se detalla a continuación)?

El código que estoy usando es la siguiente:

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

Los resultados de mi consulta SQL (de BuildQuery(), sin DISTINCT) aspecto (muy simplificado):

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 
.... 

No puedo evitar las filas duplicadas por la forma en que funciona la consulta, así que incluyo DISTINCT en la consulta SQL para que desaparezcan.

Para hacer la paginación, NHibernate genera una consulta como la siguiente (en este ejemplo es de la segunda página con 100 resultados por página):

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 

Esto funciona muy bien para la primera página, pero en las páginas siguientes me solo obtiene la mitad de los resultados esperados.

corro el SQL dentro subconsulta de NHibernate y encontraron que la fila NHibernate inserta a hacerlo es la paginación vuelve algo inesperado (incluso con distintas):

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 
.... 

Cuando NHibernate envuelve esto en una sub consulta para filtrar en la __hibernate_sort_row columna, devuelve 100 filas, pero como cada fila está duplicada, realmente solo tengo 50 filas en mi página. Esto se debe a que DISTINCT no está fusionando las filas como esperaba. (Todo esto vuelve a cómo la función ROW_NUMBER() funciona en SQL 2008 con una cláusula DISTINCT, pero es problema de NHibernate, no mío).

He resuelto este problema actualmente envolviendo la consulta en dos sub consultas y de forma manual el manejo de la paginación:

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 

Mi pregunta es: ¿cómo puedo hacer esto desde NHibernate y no mi solución manual?

Estoy usando NHibernate versión 2.1.2.

Desafortunadamente, no puedo convertir esta consulta a HQL o LINQ (a menos que alguien me pueda dar algunas semanas de tiempo libre). Tampoco puedo eliminar DISTINCT de mi consulta.

+0

parece que su solución es casi la única manera de hacerlo. http://julianjelfs.wordpress.com/2009/04/03/nhibernate-removing-duplicates-combined-with-paging/ – Vadim

+0

@Vadim - Temía que ese fuera el caso. ¿Puede dejar su comentario como respuesta y lo marcaré como aceptado? – ligos

Respuesta