【问题标题】:How to get the count from IQueryable如何从 IQueryable 获取计数
【发布时间】:2011-07-23 22:05:09
【问题描述】:

我正在我的 GridView 中实现分页。来自this的文章,我需要两个方法:

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 的值?我的意思是不重复逻辑(查询)?

【问题讨论】:

  • 你不能将返回的 IQueryable 转换为列表并进行计数吗? .ToList().count 应该给你计数。
  • 为你投票,拉姆·艾耶。谢谢。

标签: c# asp.net linq iqueryable


【解决方案1】:

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

【讨论】:

  • 老实说,Marc 中的“c”不是错字;p
  • @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);
} 

【讨论】:

  • 谢谢,但它是匿名类型。
  • 我建议将其提升为真正的类型,使其可重用。如果需要,您可以在调用此函数时切换到使用匿名类型。
  • @jonathanpeppers:在这种情况下,数据上下文必须在方法之间共享。否则会出现运行时错误。
【解决方案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);
}

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

【讨论】:

  • “另一种选择是将查询传递给分页函数” - 您可能需要稍微澄清一下。分页函数必须是通用函数才能工作,因为 Skip/Take 也仅在 IQueryable&lt;T&gt; 上运行。
  • ♦:谢谢。但我想知道为什么我不能从 IQueryable 获得计数!
  • @Jack - 好吧,你可以;但是 Count 扩展方法是为 IQueryable&lt;T&gt; 定义的 - 而不是 IQueryable
  • Hye Marc,请告诉我在 IQueryable .Any() 或 .Count() 的情况下什么是最好的。我得到一个 IQueryable,.Any() 或 .Count() 都需要时间。我只需要检查它是否有任何行。所以我应该使用.Any()。请说出哪个效果更好。
  • @Deeps 如果有疑问,为什么不直接衡量哪个表现更好?
猜你喜欢
  • 2020-12-22
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多