2011-06-02 2 views
7

Voici le code que je utilise pour retourner une liste paginée d'objets:Dapper - Cartographie multi avec une seule valeur de retour

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 resultset. Plutôt que de recourir à la concaténation de chaîne, je peux exécuter 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 semblent pas en mesure de cartographier ce 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 multi mapping mais cela devrait renvoyer un IEnumerable.

Comment mapper à ce qui suit?

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

Merci

Ben

Répondre

6

Eh bien ... vous ne ...

Vous devrez modifier votre PostModel pour inclure une propriété TotalCount ... qui est vraiment laid. Ou exécuter une dynamique et le remapper dans un Select qui est également moche.

Vous voyez, vous retournez count (*) N fois avec count(*) over() ... c'est un hack, en utilisant ce hack n'est pas nécessairement plus rapide. Je l'ai mesuré 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 autour des requêtes de pagination serait d'obtenir l'indexation correcte, c'est la clé. Mesurez perf et voir si ce hack aide réellement (lorsque l'indexation correcte est en place).

Je suis à propos des problèmes liés à la concaténation de chaînes, mais vous pouvez toujours définir des méthodes auxiliaires générales pour cela.

+0

Merci pour vos commentaires. Je pense que je vais m'en tenir à la double requête et construire des aides pour garder les choses au sec. –

Questions connexes