Как получить счет из IQueryable

Я реализую пейджинг в своем GridView. Из этой статьи мне нужны два метода:

public IQueryable BindEmployees(int startRowIndex, int maximumRows)
{
    EmployeeInfoDataContext dbEmp = new EmployeeInfoDataContext();
    var query = from emp in dbEmp.Employees
                join dept in dbEmp.Departments
                    on emp.DeptID equals dept.DeptID
                select new
                {
                    EmpID = emp.EmpID,
                    EmpName = emp.EmpName,
                    Age = emp.Age,
                    Address = emp.Address,
                    DeptName = dept.DepartmentName
                };

    return query.Skip(startRowIndex).Take(maximumRows);
} 

И

public int GetEmployeeCount()
{
    // How can I not repeat the logic above to get the count?
}

Как я могу получить значение второго метода GetEmployeeCount из первого метода BindEmployees? Я имею в виду без повторения логики (запроса)?


person Homam    schedule 27.03.2011    source источник
comment
Разве вы не можете просто преобразовать возвращенный IQueryable в список и подсчитать? ‹code› .ToList().count ‹/code› должен дать вам количество.   -  person Ram Iyer    schedule 21.01.2015
comment
Голосую за вас, Рам Айер. Спасибо.   -  person Cameron T    schedule 22.11.2019


Ответы (3)


Один из вариантов:

public IQueryable BindEmployees(int startRowIndex, int maximumRows, out int count)
{
    EmployeeInfoDataContext dbEmp = new EmployeeInfoDataContext();
    var query = from emp in dbEmp.Employees
                join dept in dbEmp.Departments
                    on emp.DeptID equals dept.DeptID
                select new
                {
                    EmpID = emp.EmpID,
                    EmpName = emp.EmpName,
                    Age = emp.Age,
                    Address = emp.Address,
                    DeptName = dept.DepartmentName
                };

    count = query.Count();
    return query.Skip(startRowIndex).Take(maximumRows);
}

Другой вариант — передать запрос в функцию пейджинга.

person Marc Gravell    schedule 27.03.2011
comment
Другой вариант — передать запрос в функцию пейджинга — возможно, вам придется немного пояснить это. Чтобы это работало, функция пейджинга должна быть общей функцией, поскольку Skip/Take также работают только с IQueryable<T>. - person Merlyn Morgan-Graham; 27.03.2011
comment
♦: Спасибо. Но мне интересно, почему я не могу получить счет от IQueryable! - person Homam; 27.03.2011
comment
@ Джек - ну, ты мог бы; но метод расширения Count определен для IQueryable<T>, а не IQueryable - person Marc Gravell; 27.03.2011
comment
Хе Марк, скажите, пожалуйста, что лучше в случае IQueryable‹T› .Any() или .Count(). Я получаю IQueryable‹T›, и оба .Any() или .Count() требуют времени. Мне просто нужно проверить, есть ли в нем какая-либо строка. Поэтому я должен использовать .Any(). Скажите, пожалуйста, что работает лучше. - person Deeps; 22.03.2013
comment
@Deeps, если есть сомнения, почему бы вам просто не измерить, что работает лучше? - person Marc Gravell; 22.03.2013

Создайте функцию для использования в обоих местах:

//Can be private or public, your choice
private IQueryable<Employee> GetQuery()
{
    EmployeeInfoDataContext dbEmp = new EmployeeInfoDataContext();
    return from emp in dbEmp.Employees
                join dept in dbEmp.Departments
                    on emp.DeptID equals dept.DeptID
                select emp;
}

Затем используйте его в обеих ваших других функциях:

public int GetEmployeeCount()
{
    return GetQuery().Count();
}

public IQueryable BindEmployees(int startRowIndex, int maximumRows)
{
    var query = from e in GetQuery()
                select new { /*Do your anonymous type here*/ };
    return query.Skip(startRowIndex).Take(maximumRows);
} 
person jonathanpeppers    schedule 27.03.2011
comment
Спасибо, но это анонимный тип. - person Homam; 27.03.2011
comment
Я предлагаю повысить его до истинного типа, что делает его многоразовым. При желании вы можете переключиться на использование анонимного типа при вызове этой функции. - person jonathanpeppers; 27.03.2011
comment
@jonathanpeppers: в ​​этом случае контекст данных должен быть разделен между методами. В противном случае вы получите ошибку времени выполнения. - person Sunil Raj; 03.12.2012

Ответ @Marc Gravell решает проблему, как указано, и, вероятно, это лучший способ. Однако в интересах предоставления вариантов вы также можете просто повторить join (поскольку вам не нужен анонимный тип при подсчете):

private int GetEmployeeCount(EmployeeInfoDataContext dbEmp)
{
    var query = from emp in dbEmp.Employees
                join dept in dbEmp.Departments on emp.DeptID equals dept.DeptID
                select dept;

    return query.Count();
}
person Bryan Watts    schedule 27.03.2011
comment
честно, c в Marc не опечатка ;p - person Marc Gravell; 27.03.2011
comment
@Marc Gravell: Ой! Я всегда следил за тобой, и я знал это. Очевидно, я только проснулась :-) - person Bryan Watts; 27.03.2011