Dapper: asignación múltiple con un único valor de retorno

dapper

Pregunta

A continuación se muestra el código que estoy usando para devolver una lista paginada de objetos:

string query2 = @"
        select count(*) as TotalCount from blogposts p where p.Deleted = 0 and p.PublishDate <= @date
        select * from (
            select p.*, 
            row_number() over(order by publishdate desc) as rownum
            from blogposts as p
            where p.Deleted = 0 and p.PublishDate <= @date
        ) seq
        where seq.rownum between @x and @y";

using (var cn = new SqlConnection(connectionString))
{
    cn.Open();
    using (var multi = cn.QueryMultiple(query2, new { x= lower, y = upper, date = DateTime.UtcNow }))
    {
        var totalCount = multi.Read<int>().Single();
        var posts = multi.Read<PostModel>().ToList();
        return new PagedList<PostModel>(posts, page, pageSize, x => totalCount);
    }
}

Aunque esto funciona, significa que tengo que definir mis criterios dos veces, una para la consulta de recuento y otra para la consulta de conjunto de resultados. En lugar de recurrir a la concatenación de cadenas, puedo ejecutar solo una consulta:

        string query = @"
                select * from (select p.*, 
                row_number() over(order by publishdate desc) as rownum,
                count(*) over() as TotalCount
                from blogposts as p) seq
                where seq.rownum between @x and @y";

Sin embargo, no parece poder mapear esto usando Dapper. No puedo usar el mismo método que el anterior porque no hay resultados múltiples. Intenté usar el mapeo múltiple, pero esto espera devolver un IEnumerable.

¿Cómo me mapearía a lo siguiente?

    public class PostList
    {
        public IEnumerable<PostModel> Posts;
        public int TotalCount { get; set; }
    }

Gracias

Ben

Respuesta aceptada

Bueno ... no lo harías ...

Tendría que modificar su modelo de publicación para incluir una propiedad TotalCount ... que es realmente fea. O ejecuta una dinámica y vuelve a asignarla en un Select que también es feo.

Usted ve, usted está devolviendo conteo (*) N veces con count(*) over() ... es un truco, el uso de este truco no es necesariamente más rápido. He medido que es más lento que ejecutar una consulta doble en algunos de mis escenarios, en particular, puede atajar algunos índices en el select count(*) ya que no está seleccionando todas las columnas. Además, el truco desactiva ciertas optimizaciones de paginación, por ejemplo, no puede agregar select top N a la consulta.

Mi recomendación sobre las consultas de paginación sería indexar correctamente, es la clave. Mida el rendimiento y vea si este truco realmente ayuda (cuando la indexación correcta está en su lugar).

Sigo las preocupaciones sobre la concatenación de cadenas, pero siempre puedes definir métodos generales de ayuda para eso.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué