2012-03-24 13 views
35

Sto provando Dapper ORM e sto interrogando una tabella di Post.Dapper. Cercapersone

Ma vorrei per ottenere risultati in pagine ...

1 - Come posso fare questo? Non c'è un aiuto per questo?

2 - Can Dapper Query restituisce un IQueryable?

Grazie, Miguel

+4

Da quando hai appena scoperto Dapper ... Spero che tu abbia anche sentito parlare di [PetaPoco] (https://github.com/toptensoftware/PetaPoco) (con supporto di paging incorporato) e [Massive] (https://github.com/robconery/massive) ... Solo FYI quindi scegli quello più adatto a te ... Sono tutti estremamente veloci e molto simili, ma ancora diversi. –

+0

vedere: http://samsaffron.com/archive/2011/09/05/Digging+ourselves+out+of+the+mess+Linq-2-SQL+created –

risposta

28

1) Dapper non ha un built-in funzione di impaginazione. Ma non è troppo difficile da implementare direttamente nella query. Esempio:

SELECT * 
FROM (SELECT ROW_NUMBER() OVER (ORDER BY InsertDate) AS RowNum, * 
      FROM  Posts 
      WHERE  InsertDate >= '1900-01-01' 
     ) AS result 
WHERE RowNum >= 1 // *your pagination parameters 
    AND RowNum < 20 //* 
ORDER BY RowNum 

richiede SQL Server 2005+

2) Dapper restituisce un IEnumerable<T>.

+4

Ma se restituisce un IEnumerable non è chiuso ? Voglio dire anche se lo cambio a IQueryable il paging sarebbe fatto in memoria e non in SQL Server. Quindi penso che il tuo approccio sia migliore ... –

+3

Sì, l'IEnumerable è "chiuso" e non ha un collegamento al contesto db come potresti conoscerlo da un contesto IQueryable con EF. – Alex

+0

Dapper v1.13 fa una .ToList() se non si modifica il buffer predefinito. Anche il codice sottostante ha già eseguito la query e sta producendo IDataReader.Read() in modo che l'utilizzo di Take and Skip non funzioni. Quindi no, Dapper non può restituire un IQueryable. – BillRob

55

Non è stato specificato un database o una versione. Se sei abbastanza fortunato da poter utilizzare il nuovissimo SQL Server 2012 e avere accesso a MSDN, puoi utilizzare le nuove splendide parole chiave OFFSET e FETCH. La seguente query salterà 20 record e tornare la prossima 5.

SELECT * FROM [Posts] 
ORDER BY [InsertDate] 
OFFSET 20 ROWS 
FETCH NEXT 5 ROWS ONLY 

Partenza http://msdn.microsoft.com/en-us/library/ms188385(v=sql.110).aspx#Offset per maggiori informazioni.

Inoltre, è abbastanza semplice copiare il modo in cui lo fa Massive e scrivere il proprio metodo di estensione per IDbConnection. Ecco il codice di Massive.

var query = string.Format("SELECT {0} FROM (SELECT ROW_NUMBER() OVER (ORDER BY {2}) AS Row, {0} FROM {3} {4}) AS Paged ", columns, pageSize, orderBy, TableName, where); 
+0

Non sapevo che SQL 2012 era già disponibile. Ho pensato che fosse su RC ... Grazie –

+7

Personalmente, io uso SqlBuilder per questa roba, scopro che le query di paginazione non banali (specialmente quelle che coinvolgono la multi-mappatura) richiedono un'attenzione particolare per ottenere risultati perf perfetti anche: http: // samsaffron.com/archive/2011/09/05/Digging+ourselves+out+of+the+mess+Linq-2-SQL+created –

+1

Parametrizza quella query !! – pimbrouwers

-8

Se non si dispone di SQL Server 2012 o avete altri DBMS, un modo per farlo è quello di dividere il paging trattamento tra i DBMS e il web server o client. --- questo è consigliato solo per piccole dimensioni del set. È possibile utilizzare la parola chiave "TOP" in Sql Server o LIMIT in MySql o ROWNUM in Oracle per ottenere il numero massimo di righe nel set di dati. Il numero di righe che si Fetch è uguale al numero che si desidera passare più il numero che si desidera prendere:

top = skip + take; 

per esempio, si potrebbe desiderare di saltare 100 righe e prendere il successivo 50:

top = 100 + 50 

Quindi l'istruzione SQL sarebbe simile a questa (sapore del server SQL)

SELECT TOP 150 Name, Modified, content, Created 
FROM  Posts 
WHERE  Created >= '1900-01-01' 

sul client: se si utilizza un linguaggio .NET, come C# e utilizzando D Apper, è possibile utilizzare LINQ per saltare un numero di righe e di prendere un certo numero di righe in questo modo:

var posts = connection.Query<Post>(sqlStatement, dynamicParameters); 
return posts?.ToList().Skip(skipValue).Take(takeValue); 
+1

Non posso raccomandare questa soluzione perché se hai molti record nel tuo database, stai trasmettendo tutti i record in memoria e quindi filtrare dal lato dell'applicazione. Dovresti filtrare e impaginare i dati sul lato DB. –

+2

La soluzione sopra chiaramente afferma che questo può essere usato per un piccolo set di dimensioni. Il paging con la sua definizione si occupa di un piccolo insieme di record. – ErnestoDeLucia

+0

Ma anche se i dati del tuo sito potrebbero essere un piccolo insieme di dati, stai ancora caricando l'intero set che potrebbe essere enorme nella memoria. –

0

Ho creato un progetto di esempio di demo il paging personalizzato Dapper, supportare l'ordinamento, i criteri e filtri:

https://github.com/jinweijie/Dapper.PagingSample

In sostanza, il metodo è simile al seguente:

Tuple<IEnumerable<Log>, int> Find(LogSearchCriteria criteria 
     , int pageIndex 
     , int pageSize 
     , string[] asc 
     , string[] desc); 

il primo valore di ritorno è l'elenco di elementi.Il secondo valore di ritorno è il conteggio totale.

Spero che aiuti.

Grazie.