.ToArray()的慢速LINQ查询 [英] Slow LINQ query for .ToArray()
问题描述
我正在使用以下查询
foreach (var callDetailsForNode_ReArrange in callDetailsForNodes_ReArrange)
{
var test = from r1 in dtRowForNode.AsEnumerable()
join r2 in dtFileRowForNode.AsEnumerable()
on r1.Field<int>("Lng_Upload_Id") equals r2.Field<int>("Lng_Upload_Id")
where ((r1.Field<string>("Txt_Called_Number") == callDetailsForNode_ReArrange.caller2.ToString()) || r1.Field<string>("Txt_Calling_Number") == callDetailsForNode_ReArrange.caller2.ToString())
select r2.Field<string>("Txt_File_Name");
var d = test.Distinct();
}
到目前为止,此查询立即运行.但是正如我所添加的
string[] str =d.ToArray();
strFileName = string.Join(",", str);
运行大约需要4-5秒钟.是什么原因使得添加.ToArray()
如此缓慢?
到此为止,该查询将立即运行.
到目前为止,除了构建表示待处理查询的延迟执行模型外,它实际上没有完成任何操作.直到您在迭代器上调用MoveNext()
(即通过foreach
,在您的情况下是通过.ToArray()
),它才会开始迭代.
所以:这需要时间,因为它正在上班.
考虑:
static IEnumerable<int> GetData()
{
Console.WriteLine("a");
yield return 0;
Console.WriteLine("b");
yield return 1;
Console.WriteLine("c");
yield return 2;
Console.WriteLine("d");
}
static void Main()
{
Console.WriteLine("start");
var data = GetData();
Console.WriteLine("got data");
foreach (var item in data)
Console.WriteLine(item);
Console.WriteLine("end");
}
这将输出:
start
got data
a
0
b
1
c
2
d
end
请注意工作是如何一次完成的-它既被延迟(a
在got data
之后出现)又被假脱机处理(我们没有得到a
,...,d
,0
,... 2
).
相关:通过评论,这大致就是Distinct()
的工作方式:
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source) {
var seen = new HashSet<T>();
foreach(var item in source) {
if(seen.Add(item)) yield return item;
}
}
...
和新的Join
操作:
public static string Join(this IEnumerable<string> source, string separator) {
using(var iter = source.GetEnumerator()) {
if(!iter.MoveNext()) return "";
var sb = new StringBuilder(iter.Current);
while(iter.MoveNext())
sb.Append(separator).Append(iter.Current);
return sb.ToString();
}
}
并使用:
string s = d.Join(",");
I am using following query
foreach (var callDetailsForNode_ReArrange in callDetailsForNodes_ReArrange)
{
var test = from r1 in dtRowForNode.AsEnumerable()
join r2 in dtFileRowForNode.AsEnumerable()
on r1.Field<int>("Lng_Upload_Id") equals r2.Field<int>("Lng_Upload_Id")
where ((r1.Field<string>("Txt_Called_Number") == callDetailsForNode_ReArrange.caller2.ToString()) || r1.Field<string>("Txt_Calling_Number") == callDetailsForNode_ReArrange.caller2.ToString())
select r2.Field<string>("Txt_File_Name");
var d = test.Distinct();
}
Upto here this query run in no time. But as I added
string[] str =d.ToArray();
strFileName = string.Join(",", str);
It takes almost 4-5 seconds to run. What makes it so slow on adding .ToArray()
?
Upto here this query run in no time.
Up to here, it hasn't actually done anything, except build a deferred-execution model that represents the pending query. It doesn't start iterating until you call MoveNext()
on the iterator, i.e. via foreach
, in your case via .ToArray()
.
So: it takes time because it is doing work.
Consider:
static IEnumerable<int> GetData()
{
Console.WriteLine("a");
yield return 0;
Console.WriteLine("b");
yield return 1;
Console.WriteLine("c");
yield return 2;
Console.WriteLine("d");
}
static void Main()
{
Console.WriteLine("start");
var data = GetData();
Console.WriteLine("got data");
foreach (var item in data)
Console.WriteLine(item);
Console.WriteLine("end");
}
This outputs:
start
got data
a
0
b
1
c
2
d
end
Note how the work doesn't all happen at once - it is both deferred (a
comes after got data
) and spooling (we don't get a
,...,d
,0
,...2
).
Related: this is roughly how Distinct()
works, from comments:
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source) {
var seen = new HashSet<T>();
foreach(var item in source) {
if(seen.Add(item)) yield return item;
}
}
...
and a new Join
operation:
public static string Join(this IEnumerable<string> source, string separator) {
using(var iter = source.GetEnumerator()) {
if(!iter.MoveNext()) return "";
var sb = new StringBuilder(iter.Current);
while(iter.MoveNext())
sb.Append(separator).Append(iter.Current);
return sb.ToString();
}
}
and use:
string s = d.Join(",");
这篇关于.ToArray()的慢速LINQ查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!