2013-08-28 49 views
18

Tôi đang sử dụng Khung thực thể để nhận tổng số hàng cho một bảng. Tôi chỉ muốn đếm số hàng, không có mệnh đề where hay bất cứ thứ gì như thế. Truy vấn sau hoạt động, nhưng chậm. Mất khoảng 7 giây để trả lại số 4475.Nhận tổng số hàng trong Entity Framework

Tôi đoán ở đây là nó đang lặp qua toàn bộ bảng, giống như cách thức hoạt động của phương thức mở rộng IEnumerable.Count().

Có cách nào tôi có thể nhận tổng số hàng "nhanh" không? Có cách nào tốt hơn?

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

thế nào để đếm hàng trong EntityFramework mà không cần tải nội dung? http://stackoverflow.com/questions/890381/how-to-count-rows-within-entityframework-without-loading-contents – sevdalone

+3

Hãy chắc chắn rằng context.Logs là một DbSet, IDbSet, hoặc một IQueryable, không phải là một IEnumerable. Nếu nó là một IEnumerable, toàn bộ bảng sẽ được lấy và tính. Nếu nó là một IQueryable, truy vấn sẽ được tạo ra để đếm các hàng trong cơ sở dữ liệu sẽ giống như "SELECT COUNT (*) FROM dbo.Logs" (Nếu nó là IdbSet hoặc DbSet, nó sẽ được coi là một IQueryable) – Grax

Trả lời

6

Đó là cách để tính số lượng hàng của bạn bằng cách sử dụng Khung thực thể. Bạn có thể sẽ thấy hiệu suất nhanh hơn trên các truy vấn + thứ hai vì có chi phí khởi tạo lần đầu tiên bạn chạy nó. (Và nó sẽ tạo ra một truy vấn Select Count() ở đây, không lặp qua từng hàng).

Nếu bạn quan tâm đến một cách nhanh hơn để có được số lượng hàng thô trong bảng, thì bạn có thể muốn thử sử dụng một ORM nhỏ như Dapper hoặc OrmLite. Bạn cũng nên đảm bảo rằng bảng của bạn được xác định đúng (ít nhất, nó có một khóa chính), vì không thực hiện được điều này cũng có thể ảnh hưởng đến thời gian để đếm các hàng trong bảng.

1

Nếu bạn có quyền truy cập để làm như vậy, sẽ nhanh hơn khi truy vấn các bảng sys để lấy thông tin này.

Ví dụ:

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 nói sys.partitions.rows "Cho biết số lượng gần đúng của các hàng trong phân vùng này." http://technet.microsoft.com/en-us/library/ms175012.aspx – cadrell0

+0

Cảm ơn, tôi đã thay đổi nó để sử dụng sysindexes thay thế. – Khan

+2

http://technet.microsoft.com/en-us/library/ms190283.aspx "Tính năng này sẽ bị xóa trong phiên bản tương lai của Microsoft SQL Server. Tránh sử dụng tính năng này trong công việc phát triển mới và lập kế hoạch sửa đổi ứng dụng hiện đang sử dụng tính năng này. " Ngoài ra, từ tài liệu, có vẻ như điều này có thể không hoạt động nếu bảng được phân đoạn. – cadrell0

7

Bạn thậm chí có thể bắn liệu truy vấn SQL sử dụng khuôn khổ thực thể như sau:

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