Dapper - Multi Mapping avec une seule valeur de retour

dapper

Question

Voici le code que j'utilise pour renvoyer une liste paginée d'objets:

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);
    }
}

Bien que cela fonctionne, cela signifie que je dois définir deux fois mes critères, une fois pour la requête count et une fois pour la requête du jeu de résultats. Plutôt que de recourir à la concaténation de chaînes, je ne peux exécuter qu’une seule requête:

        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";

Cependant, je ne semble pas capable de mapper ceci en utilisant Dapper. Je ne peux pas utiliser la même méthode que ci-dessus car il n'y a pas de résultats multiples. J'ai essayé d'utiliser le mappage multiple, mais cela suppose de renvoyer un fichier IEnumerable.

Comment puis-je mapper avec les éléments suivants?

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

Merci

Ben

Réponse acceptée

Eh bien ... tu ne ferais pas ...

Vous devez modifier votre PostModel pour inclure une propriété TotalCount ... qui est vraiment moche. Ou exécutez une dynamique et remappez-la dans un Select qui est également moche.

Vous voyez, vous retournez count (*) N fois avec count(*) over() ... c'est un hack, utiliser ce hack n'est pas forcément plus rapide. J'ai mesuré qu'il est plus lent que d'exécuter une double requête dans certains de mes scénarios, en particulier vous pouvez raccourcir certains index dans le select count(*) puisque vous ne sélectionnez pas toutes les colonnes. De plus, le hack désactive certaines optimisations de pagination, par exemple, vous ne pouvez pas ajouter select top N à la requête.

Ma recommandation concernant les requêtes de pagination serait d'obtenir une indexation correcte, c'est la clé. Mesurer les perf et voir si ce hack aide réellement (lorsque l'indexation correcte est en place).

Je suis au sujet des préoccupations concernant la concaténation de chaînes, mais vous pouvez toujours définir des méthodes d’assistance générales pour cela.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi