Performance of LINQ Any vs FirstOrDefault != null
在我贡献的开源项目(OSP)代码中有多个位置,在那里必须确定集合中的元素是否满足某个条件。
我见过在某些情况下使用linq表达
我现在已经到了必须对从查询到数据库的集合进行一些迭代的地步,并且想要优化运行时。
所以我认为
在
在
编辑:正如杰克逊·波普提到并链接了相关的msdn文章,上述说法是不正确的。
我的想法是正确的还是遗漏了什么?
你在这里混东西。您谈论的是集合,但似乎没有使用Linq to对象,而是在查询数据库。
Linq到对象:
1 2 3 4 5 6 | foreach (TSource source1 in source) { if (predicate(source1)) return source1; } return default (TSource); |
1 2 3 4 5 6 | foreach (TSource source1 in source) { if (predicate(source1)) return true } return false; |
Linq到某些数据库:您正在使用实体框架、Linq to SQL或NHibernate,并在相应的数据上下文中使用
这意味着,性能差异源于LINQ提供程序如何将代码转换为SQL,因此最好是先检查创建的语句。它们是等价的吗?或者它们是非常不同的(
http://msdn.microsoft.com/en-us/library/bb534972.aspx
我希望演出非常相似。注意,
这个问题的问题是它不是在上下文中被问到的。我提供了一个答案,因为我在代码审查中看到了很多,这让我很困扰。Linq不应该成为停止思考的借口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | var people = new [] {"Steve","Joe" }; if (people.Any(s => s =="Joe")) { var joe = people.First(s => s =="Joe"); // do something with joe } // if people is 1,000,000 people and joe is near the end do we want BigO to approach 2N here at worst case ? var joe1N = people.FirstOrDefault(s => s =="Joe"); if (joe1N != null) { // do something with joe } // or do we want to ensure worst case is N by simply using a variable ? |
为什么在找到满足条件的元素之后还要继续?如果条件适用于1个元素,则该元素符合"any"的条件。
我认为它们应该表现得差不多,但是any()确实更清楚地表达了您的意图。
我们可以使用.count(x=>x…)!=0而不是使用.any(x=>x…)或.first或default(x=>x…)!=空
因为linq的查询生成在下面,
(在any()中,我认为不需要第二个(不存在)条件。)
.any(x=>x.col_1='xxx')
1 2 3 4 5 6 7 8 9 10 11 | (@p__linq__0 varchar(8000))SELECT CASE WHEN ( EXISTS (SELECT 1 AS [C1] FROM [dbo].[Table_X] AS [Extent1] WHERE [Extent1].[Col_1] = @p__linq__0 )) THEN cast(1 as bit) WHEN ( NOT EXISTS (SELECT 1 AS [C1] FROM [dbo].[Table_X] AS [Extent2] WHERE [Extent2].[Col_1] = @p__linq__0 )) THEN cast(0 as bit) END AS [C1] FROM ( SELECT 1 AS X ) AS [SingleRowTable1] |
.FirstOrDefault(x=>x.col_1='xxx')!=空
1 2 3 4 5 6 7 | (@p__linq__0 varchar(8000))SELECT TOP (1) [Extent1].[Col_1] AS [Col_1], [Extent1].[Col_2] AS [Col_2], ... [Extent1].[Col_n] AS [Col_n] FROM [dbo].[Table_X] AS [Extent1] WHERE [Extent1].[Col_1] = @p__linq__0 |
.count(x=>x.col_1='xxx')!= 0
1 2 3 4 5 6 7 | (@p__linq__0 varchar(8000))SELECT [GroupBy1].[A1] AS [C1] FROM ( SELECT COUNT(1) AS [A1] FROM [dbo].[Table_X] AS [Extent1] WHERE [Extent1].[Col_1] = @p__linq__0 ) AS [GroupBy1] |
我的两分钱…
我对任何()都有很大的性能问题。我正在使用Telerik网格显示相关数据的列表,即,
-我有一张"人"桌
-"公司"表
-"人民公司"链接表
-"人物角色"链接表
-以及"rol"表,其中包含主类别、子类别和说明。
该视图混合了数据,并具有一些属性,这些属性按需加载有关特定角色(管理员、报告者、管理者)的数据。
1 2 3 | var x = GetPeople().Where(p => p.ROLs.Any(i => i.USO_Id == MainCatId && i.TUP_Id == (int)RolType) && p.PER_Id != per_id); var x = GetPersonas().Where(p => p.ROLs.FirstOrDefault(i => i.USO_Id == MainCatId && i.TUP_Id == (int)RolType) != null && p.PER_Id != per_id); |
我的网格使用Ajax,使用"any"加载需要10秒,使用"firstordefault"加载3秒或更少。没有花时间调试它,作为拦截来自Telerik组件和我的模型的调用的条件。
希望这有帮助…所以好好测试一下:)