2013-08-28 14 views
18

Sto utilizzando Entity Framework per ottenere il numero totale di righe per una tabella. Voglio semplicemente il conteggio delle righe, nessuna clausola where o qualcosa del genere. La seguente query funziona, ma è lenta. Ci sono voluti circa 7 secondi per restituire il conteggio di 4475.Ottenere il numero totale di righe in Entity Framework

La mia ipotesi qui è che sta iterando attraverso l'intera tabella, proprio come funziona il metodo di estensione IEnumerable.Count().

C'è un modo per ottenere il numero totale di righe "rapidamente"? C'è un modo migliore?

public int GetLogCount() 
    { 
     using (var context = new my_db_entities(connection_string)) 
     { 
      return context.Logs.Count(); 
     } 
    } 
+2

come contare righe all'interno EntityFramework senza caricare i contenuti? http://stackoverflow.com/questions/890381/how-to-count-rows-within-entityframework-without-loading-contents – sevdalone

+3

Assicurarsi che context.Logs sia un DbSet, IDbSet o un IQueryable, non un IEnumerable. Se è un oggetto IEnumerable, verrà recuperata e contata l'intera tabella. Se è un IQueryable, la query verrà generata per contare le righe nel database che sarà qualcosa come "SELECT COUNT (*) FROM dbo.Logs" (Se è un IdbSet o DbSet, sarà trattato come un IQueryable) – Grax

risposta

6

Questo è il modo per ottenere il numero di righe utilizzando Entity Framework. Probabilmente vedrai prestazioni più veloci nelle seconde + query poiché c'è un costo di inizializzazione la prima volta che lo esegui. (E dovrebbe generare una query Select Count() qui, non iterando attraverso ogni riga).

Se si è interessati a un modo più rapido per ottenere il conteggio delle righe non elaborate in una tabella, è possibile provare a utilizzare un mini ORM come Dapper o OrmLite.

È inoltre necessario assicurarsi che la tabella sia definita correttamente (per lo meno, che abbia una chiave primaria), in quanto un errore non può influire sul tempo di conteggiare le righe nella tabella.

1

Se si ha accesso a tale operazione, sarebbe molto più rapido interrogare le tabelle sys per estrarre queste informazioni.

E.g.

public Int64 GetLogCount() 
{ 
    var tableNameParam = new SqlParameter("TableName", "Logs"); 
    var schemaNameParam = new SqlParameter("SchemaName", "dbo"); 
    using (var context = new my_db_entities(connection_string)) 
    { 
     var query = @" 
      SELECT ISNULL([RowCount],0) 
      FROM (
       SELECT SchemaName, 
         TableName, 
         Sum(I.rowcnt) [RowCount] 
       FROM sysindexes I 
         JOIN sysobjects O (nolock) ON I.id = o.id AND o.type = 'U' 
         JOIN (
          SELECT so.object_id, 
            ss.name as SchemaName, 
            so.name as TableName 
           FROM sys.objects SO (nolock) 
            JOIN sys.schemas SS (nolock) ON ss.schema_id = so.schema_id 
         ) SN 
          ON SN.object_id = o.id 
       WHERE I.indid IN (0, 1) 
       AND  TableName = @TableName AND SchemaName = @SchemaName 
       GROUP BY 
         SchemaName, TableName 
      ) A 
     "; 

     return context.ExecuteStoreQuery<Int64>(query, tableNameParam, schemaNameParam).First(); 
    } 
} 
+0

MSDN dice sys.partitions.rows "Indica il numero approssimativo di righe in questa partizione." http://technet.microsoft.com/en-us/library/ms175012.aspx – cadrell0

+0

Grazie, l'ho cambiato per usare invece sysindexes. – Khan

+2

http://technet.microsoft.com/en-us/library/ms190283.aspx "Questa funzionalità verrà rimossa in una versione futura di Microsoft SQL Server. Evitare di utilizzare questa funzionalità in un nuovo lavoro di sviluppo e pianificare di modificare le applicazioni che attualmente usa questa funzione. " Inoltre, dalla documentazione, sembra che questo potrebbe non funzionare se la tabella è partizionata. – cadrell0

7

Si può anche sparare Raw query SQL tramite Entity Framework, come di seguito:

var sql = "SELECT COUNT(*) FROM dbo.Logs"; 
var total = context.Database.SqlQuery<int>(sql).Single(); 
Problemi correlati