请考虑以下代码示例:
IEnumerable<Y> myEnumeration = *some linq stuff into a datatable*
If (myEnumeration.Count() > X)
{
foreach(Y bla in myEnumeration)
{
// do something
}
}
这会导致枚举2次吗?伯爵 - 召唤+ foreach?如果是这样,有没有办法避免其中一个枚举?
提前致谢
已编辑myEnumeration.Count - &gt; myEnumeration.Count()(扩展方法)
答案 0 :(得分:3)
我把这段代码放到LinqPad让我展示生成的SQL:
IEnumerable<MyTable> myEnumeration = MyTable;
if (myEnumeration.Count() > 1)
{
foreach(MyTable bla in myEnumeration)
{
// do something
}
}
生成的SQL如下:
SELECT * FROM [MyTable] AS [t0]
GO
SELECT *
FROM [MyTable] AS [t0]
所以是的,数据将从数据库中检索两次。 考虑
List<Y> myEnumeration = *some linq stuff into a datatable* **.ToList();**
答案 1 :(得分:3)
是的,这将为您提供两个数据库调用。 Count()
将执行以下查询:
SELECT COUNT(1) FROM Table WHERE Blah
然后GetEnumerator()
将执行获取所有必填字段的查询:
SELECT Id, Foo, Bar FROM Table WHERE Blah
实际上没有一个正确的答案。你应该考虑:
根据你的不同,你应该做出决定。
这是扩展名:
public static IEnumerable<T> TakeIfMoreThan<T>(
this IEnumerable<T> source, int count)
{
List<T> buffer = new List<T>(count);
using (var iterator = source.GetEnumerator())
{
while (buffer.Count < count && iterator.MoveNext())
buffer.Add(iterator.Current);
if (buffer.Count < count)
{
yield break;
}
else
{
foreach (var item in buffer)
yield return item;
buffer.Clear();
while (iterator.MoveNext())
yield return iterator.Current;
}
}
}
用法很简单:
foreach(Y bla in myEnumeration.TakeIfMoreThan(X))
{
// do something
}
因此,您不需要将所有查询结果转储到内存列表中。您将使用单个数据库调用(但它将查询所有项目字段)。如果结果数量少于所需数量,则不会枚举项目。
答案 2 :(得分:2)
如果Count
不是属性,而是方法Enumerable.Count
(如我所料)。在这种情况下,我建议的是事先将其列入一个列表:
List<Y> myList = *some linq stuff into a datatable*.ToList();
if (myList.Count > X)
foreach (Y bla in myList)
//do something
答案 3 :(得分:1)
它将为您生成两个查询:
SELECT COUNT(*) FROM sometable
和
SELECT * FROM sometable
既不是一次也不是两次。这将是两个单独的请求,但只有第二个请求将提取数据。第一个将返回数字,并将更快。如果您希望在严格的一个请求中执行此操作,请在查询结尾处使用.ToList()
。然后它将通过列表。您也可以在SQL事件探查器中进行检查。请记住,在某些情况下,两种查询方法可能更安全,因此您不会突然开始拉出数百万行。