TotalRowCount с подкачкой в ​​Linq2SQL - PullRequest
1 голос
/ 08 июня 2011

Я получаю выгружаемый источник данных из довольно сложного запроса linq. Моя проблема заключается в том, что выполнение занимает вдвое больше времени, так как мне нужно получить общее количество строк перед применением подкачки для вычисления nr. страниц для отображения. (запрос будет выполнен дважды)

Могу ли я как-нибудь сделать это более оптимальным способом? Как, например, использовать SQL @@ rowcount?

Примерно так выглядит запрос прямо сейчас. (используя Dynamic 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

1 Ответ

3 голосов
/ 09 июня 2011

Linq2Sql фактически переведет использование Skip & Take в инструкцию SQL, так что даже если вы можете получить @@ RowCount, значение будет не больше, чем ваш параметр take.

Если мы возьмем следующий простой пример (взято из MSDN http://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 будет равен количеству строк, возвращаемых запросом, а не всему набору результатов.

...