如何从IQueryable中获取计数

26

我正在为我的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?
}

我怎样可以从第一个方法BindEmployees获取第二个方法GetEmployeeCount的值?我的意思是不重复逻辑(查询)的情况下。


1
你不能直接将返回的IQueryable转换为列表并获取计数吗?<code>.ToList().Count</code>应该可以给你计数。 - Ram Iyer
给你点赞,Ram Iyer。谢谢。 - Cameron
3个回答

25

其中一个选择是:

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);
}

另一种选择是将查询传递到分页函数中。


另一个选项是将查询传递到分页函数中。需要稍微澄清一下,为了使其工作,分页函数必须是通用函数,因为Skip/Take也仅对IQueryable<T>进行操作。 - Merlyn Morgan-Graham
♦:谢谢。但我想知道为什么我无法从IQueryable获取计数! - Homam
2
@Jack - 嗯,你可以这样做;但是Count扩展方法是为IQueryable<T>定义的,而不是IQueryable - Marc Gravell
嗨,马克,请告诉我在IQueryable<T>的情况下什么最好。Any()还是Count()?我得到了一个IQueryable<T>,而且无论是.Any()还是.Count()都需要时间。我只需要检查它是否有任何行。所以我应该使用.Any()。请告诉我哪个性能更好。 - Deeps
4
如果你有疑问,为什么不直接“量”一下哪个表现更好呢? - Marc Gravell

2
制作一个可以在两个地方使用的函数:
//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);
} 

1
谢谢,但这是匿名类型。 - Homam
我建议将其提升为真正的类型,这样可以使其可重用。如果需要,您可以在调用此函数时切换到使用匿名类型。 - jonathanpeppers
在这种情况下,数据上下文必须在方法之间共享。否则,您将会收到运行时错误。 - Sunil Raj

0

@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();
}

4
老实说,Marc 中的 "c" 不是打错了的 ;p - Marc Gravell
@Marc Gravell:糟糕!我一直在关注你,而我也知道这点。显然我刚刚醒来 :-) - Bryan Watts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接