【发布时间】:2011-03-13 22:48:52
【问题描述】:
对于我编写的每个 LINQ 查询,我总是使用 foreach 循环来遍历结果。现在,我有一个程序,我想获取结果的前 50 行,对这些行进行一些计算,然后获取结果的下 50 行等。
使用 LINQ 和 C# 执行此操作的标准方法是什么?
【问题讨论】:
对于我编写的每个 LINQ 查询,我总是使用 foreach 循环来遍历结果。现在,我有一个程序,我想获取结果的前 50 行,对这些行进行一些计算,然后获取结果的下 50 行等。
使用 LINQ 和 C# 执行此操作的标准方法是什么?
【问题讨论】:
.Skip().Take() 在这种情况下将是最好的方法(就清晰而言)。例如:
var results = db.Table.Select(); // Your query here
int rowCount = results.Count(); // Count rows once and store
for(int i = 0; i <= rowCount; i += 50)
{
var paged = results.Skip(i).Take(50);
// do the calculations with the groups of 50 here
}
值得注意的是,即使这看起来更清楚(您从结果中抽取 50 个组),但每次调用 Skip() 和 Take() 时,都可能需要重新枚举集合...这实际上比简单地使用foreach 一次枚举结果效率低。
【讨论】:
IEnumerable<>,这将遍历集合多次
IQueryable 对象,则很有可能将分页移至数据库。在这些情况下,我强烈建议采用这种方法。
在不了解数据和/或计算的性质的情况下,执行此操作的“良好标准”方法可能是 foreach 循环!
如果您能提供一些有关数据性质和您想要执行的计算的信息,将会有所帮助。取决于此,最佳答案可能是 foreach、Skip/Take、GroupBy 或其他任何东西。
【讨论】:
有这样的效果
var page = (From c In db.Customers Order By c.ContactName, c.City Descending
Select c).Skip(50).Take(50)
【讨论】:
您可以通过 ie 使用组:
data.Select((item, index) => new {item, index}).GroupBy(g => g.index / 50)
然后您将对每个组进行操作。
【讨论】:
使用.Skip(...).Take(...) 将用于分页。但需要考虑的是,再次IEnumerable<...> 这将在每次处理时重新计算可枚举。这是消耗而不是可重置的东西,您可能会遇到问题。这个方法集可以解决这个问题。
public static class EnumerableEx
{
public static IEnumerable<IEnumerable<T>> AsPages<T>(
this IEnumerable<T> set, int pageLength)
{
using (var e = set.GetEnumerator())
while (true)
yield return GetPage(e, pageLength);
}
private static IEnumerable<T> GetPage<T>(
IEnumerator<T> set, int pageLength)
{
for (var position = 0;
position < pageLength && set.MoveNext();
position++)
yield return set.Current;
}
}
...这是一个为什么它很重要的用法示例。
class Program
{
private static int _last = 0;
private static IEnumerable<int> GetValues()
{
while (true)
yield return _last++;
}
static void Main(string[] args)
{
for (var i = 0; i < 3; i++)
foreach (var value in GetValues().Skip(5 * i).Take(5))
Console.Write(value + ",");
// 0,1,2,3,4,10,11,12,13,14,25,26,27,28,29,
Console.WriteLine();
_last = 0;
foreach (var page in GetValues().AsPages(5).Take(3))
foreach (var value in page)
Console.Write(value + ",");
// 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
}
}
【讨论】: