Dapper - Multi Mapping con un unico valore di ritorno

dapper

Domanda

Di seguito è riportato il codice che sto utilizzando per restituire un elenco di oggetti a pagine:

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

Sebbene funzioni, significa che devo definire i miei criteri due volte, una volta per la query di conteggio e una volta per la query con i risultati. Invece di ricorrere alla concatenazione di stringhe, posso eseguire solo una query:

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

Tuttavia, non riesco a mapparlo usando Dapper. Non posso usare lo stesso metodo di cui sopra perché non ci sono più risultati. Ho provato a utilizzare la mappatura multipla, ma mi aspetto di restituire un oggetto IEnumerable.

Come dovrei mappare al seguente?

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

Grazie

Ben

Risposta accettata

Beh ... non lo faresti ...

Dovresti modificare il tuo PostModel per includere una proprietà TotalCount ... che è davvero brutta. O eseguire una dinamica e rimapparla in un Select che è anche brutto.

Vedi, stai restituendo count (*) N volte con count(*) over() ... è un hack, usare questo hack non è necessariamente più veloce. Ho rilevato che è più lento dell'esecuzione di una doppia query in alcuni dei miei scenari, in particolare è possibile selezionare alcuni indici nel select count(*) poiché non si selezionano tutte le colonne. Inoltre l'hack disabilita alcune ottimizzazioni di paging, ad esempio non è possibile aggiungere la select top N alla query.

La mia raccomandazione sulle query di paging sarebbe quella di ottenere l'indicizzazione corretta, è la chiave. Misurare perf e vedere se questo hack aiuta in realtà (quando l'indicizzazione corretta è a posto).

Seguo le preoccupazioni relative alla concatenazione delle stringhe, ma è sempre possibile definire metodi di supporto generali per questo.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow