在计数和跳过时可能多次枚举IEnumerable

时间:2012-05-21 00:19:58

标签: linq-to-sql c#-4.0 count ienumerable skip-take

我正在为Linq2Sql中的数据表准备数据

此代码突出显示为“可能多次枚举IEnumerable”(在Resharper中)

// filtered is an IEnumerable or an IQueryable

var total = filtered.Count();

var displayed = filtered
                .Skip(param.iDisplayStart)
                .Take(param.iDisplayLength).ToList(); 

我100%肯定Resharper是对的。

如何重写此内容以避免警告

为了澄清,我知道我可以在过滤结束时放置一个ToList,只对数据库执行一次查询,例如。

 var filteredAndRun = filtered.ToList();

 var total = filteredAndRun.Count();

 var displayed = filteredAndRun
                .Skip(param.iDisplayStart)
                .Take(param.iDisplayLength).ToList(); 

但这会带来比我想通过网络传输更多的数据。

我期待着我不能吃蛋糕而且也吃它。 :(

2 个答案:

答案 0 :(得分:2)

听起来你更关注IQueryable<T>而不是IEnumerable<T>的多次枚举。

但是,在你的情况下,没关系。

Count调用应转换为简单且非常快速的SQL计数查询。它只是第二个实际带回任何记录的查询。

如果它是IEnumerable<T>,那么数据就在内存中,无论如何它都会超快。

我会保持您的代码完全相同,只有当您发现性能问题严重时才会担心性能调整。 : - )

答案 1 :(得分:0)

您也可以执行类似

的操作
count = 0;
displayed = new List();
iDisplayStop = param.iDisplayStart + param.iDisplayLength;
foreach (element in filteredAndRun) {
    ++count;
    if ((count < param.iDisplayStart) || (count > iDisplayStop))
          continue;
    displayed.Add(element);
}

显然,这是伪代码,并且我可能在边缘条件下是一个接一个,但是该算法只用一次迭代就可以获得计数,并且只有最后显示的项目列表。