如何使用LinQ来提高性能

时间:2012-04-10 22:14:43

标签: c# performance

我有这个LinQ:

var IPI = item.INV_TAXES.Where(t => t.TAXTYPES.TAXNAME == "IPI")
                        .Select(t => new {TOT_AMT = t.TAXVALUE, t.TAXFACTOR, t.TAXBASE})
                        .First();

然后在代码中我将下一行调用大约10次:

PerformSomeCalculation(IPI.TOT_AMT);
PerformAnotherStuff(IPI.TOT_AMT,IPI.TAXVALUE);
PerformSomethingElse(IPI.TAXBASE);

我想知道每次调用IPI的每个成员,LinQ是执行还是第一次分配它?

首先将IPI成员分配给变量是否更好?

decimal IPI_TOT_AMT = IPI.TOT_AMT,
        IPI_TAXVALUE = IPI.TAXVALUE,
        IPI_TAXBASE = IPI.TAXBASE;

然后使用它们。

感谢所有建议。

5 个答案:

答案 0 :(得分:7)

首先,停止在你的代码中出现。

你是对的。每次访问时都会执行查询 fresh ,因为结果可能会发生变化。但First的结果不是查询,而是值。

也就是说,如果你这样做了:

var query = whatever.Where(whatever).Select(whatever);
Console.WriteLine(query.First());
Console.WriteLine(query.First());

然后第一行创建,第二行执行,第三行再次执行 。第二次调用First时,查询不知道第一个结果是否不同,因此它再次运行查询。

相比之下,如果你这样做:

var query = whatever.Where(whatever).Select(whatever);
var first = query.First();
Console.WriteLine(first);
Console.WriteLine(first);

然后第一行创建查询,第二行执行查询并存储结果,第三行和第四行报告存储的结果。

答案 1 :(得分:4)

在您提供的代码中,LINQ查询仅在您调用.First()方法时运行。

通过在访问变量之前将成员分配给变量,将不会有明显的性能提升。

请注意,并非所有LINQ语句都是如此。例如,如果你说过:

var IPIs = item.INV_TAXES.Where(t => t.TAXTYPES.TAXNAME == "IPI")
                     .Select(t => new {TOT_AMT = t.TAXVALUE, t.TAXFACTOR, t.TAXBASE});

...然后将IPI传递给几种方法,最终可能会有单独的数据库往返。为了避免这个问题,您可以在分配变量之前调用.ToList()强制立即进行评估。但在这种情况下,调用.First()会有效地做同样的事情。

答案 2 :(得分:1)

  

如果我每次打电话给IPI的每个成员,LinQ,我都会发出警告   每次或仅在我分配时第一次执行?

不,查询只执行一次 - IPI是具有一堆原始属性(实际上是小数)的匿名类型的实例。此对象不再与查询相关联 - 您的查询已执行并作为First()扩展方法的结果返回此对象,该方法强制立即执行并返回输入集合中的第一个项目。

答案 3 :(得分:1)

Eric Lippert的回答解释了你想要的一切。但是,如果您想进一步优化,可以尝试使用CompiledQuery.Compile方法来存储和重用查询。

有关更多信息,请查看msdn。你可以从这里开始: http://msdn.microsoft.com/cs-cz/library/bb399335.aspx

答案 4 :(得分:0)

First()方法执行linq查询并返回第一个对象 此对象的类型与您使用的任何其他对象类似,唯一的区别是类定义是由编译器编写的。

因此,当您使用对象

时,不再执行任何操作