在Linq2SQL中使用分页的TotalRowCount

本文关键字:分页 TotalRowCount Linq2SQL | 更新日期: 2023-09-27 17:58:53

我从一个相当复杂的linq查询中获得一个分页数据源。我的问题是执行需要两倍的时间,因为我需要在应用分页之前获得总行数,以便计算要显示的页数。(查询将执行两次)

有没有什么方法可以让我以更优化的方式做到这一点?喜欢以某种方式使用SQL的@@rowcount吗?

这大致就是查询现在的样子。(使用动态linq)

    public IList<User> GetPagedUsers(string filter, string sort, int skip, 
       int take, out int totalRows)
    {
            using(var dbContext = new DataContext())
            {
               IQueryable<User> q = GetVeryComplexQuery(dbContext);
               //Apply filter if exists
               if (!string.IsNullOrEmpty(filter))
                   q = q.Where(filter);
               //Set total rows to the out parameter
               totalRows = q.Count(); //Takes 4 sec to run
               //Apply sort if exists
               if (!string.IsNullOrEmpty(sort))
                   q = q.OrderBy(sort);
               //Apply paging and return
               return q.Skip(skip).Take(take).ToList(); //Takes 4 sec to run
            }
    }

例如,为什么这不起作用?

TblCompanies.Dump(); //150 rows
ExecuteQuery<int>("select @@ROWCOUNT").Dump(); //returns 0

在Linq2SQL中使用分页的TotalRowCount

Linq2Sql将实际翻译Skip&考虑SQL语句,因此即使您可以获得@@RowCount,该值也不会比您的Take参数大。

如果我们举以下简单的例子(摘自MSDNhttp://msdn.microsoft.com/en-us/library/bb386988.aspx)。

IQueryable<Customer> custQuery3 =
    (from custs in db.Customers
     where custs.City == "London"
     orderby custs.CustomerID
     select custs)
    .Skip(1).Take(1);
foreach (var custObj in custQuery3)
{
    Console.WriteLine(custObj.CustomerID);
}

生成以下SQL

SELECT TOP 1 [t0].[CustomerID], [t0].[CompanyName],
FROM [Customers] AS [t0]
WHERE (NOT (EXISTS(
    SELECT NULL AS [EMPTY]
    FROM (
        SELECT TOP 1 [t1].[CustomerID]
        FROM [Customers] AS [t1]
        WHERE [t1].[City] = @p0
        ORDER BY [t1].[CustomerID]
        ) AS [t2]
    WHERE [t0].[CustomerID] = [t2].[CustomerID]
    ))) AND ([t0].[City] = @p1)
ORDER BY [t0].[CustomerID]

因此,您可以看到跳过实际上发生在SQL语句内部,因此@@RowCount将等于查询返回的行数,而不是整个结果集。