使用Entity Framework,最好使用.First()或.Take(1)作为“TOP 1”吗?

时间:2012-05-04 20:04:16

标签: sql linq entity-framework ienumerable linq-to-objects

我们正在实施一些EF数据存储库,我们有一些查询包括TOP 1

我看过很多建议使用.Take(1)的帖子 我正在审核的代码使用.First()

据我所知,这两个对象分配都会产生相同的结果,但它们是否真的解析为同一个查询?查询数据库时,两个请求实际上是TOP 1吗?或者他们会将查询完整地执行到可枚举中,然后只需获取集合中的第一个条目吗?

此外,如果我们使用.FirstOrDefault()那么为什么我们应该期待任何不同的行为呢?我知道当使用IEnumerable时,在空集合上调用.First()会抛出,但如果 实际上只是将查询更改为包含TOP 1那么我应该绝对不会.First().FirstOrDefault()之间的功能差异......对吗?

或者,是否有一些比这些Enumerable扩展更好的方法来使查询执行TOP 1

5 个答案:

答案 0 :(得分:63)

来自LINQPad

<强> C#

age_Centers.Select(c => c.Id).First();
age_Centers.Select(c => c.Id).FirstOrDefault();
age_Centers.Select(c => c.Id).Take(1).Dump();

<强> SQL

SELECT TOP (1) [t0].[Id]
FROM [age_Centers] AS [t0]
GO

SELECT TOP (1) [t0].[Id]
FROM [age_Centers] AS [t0]
GO

SELECT TOP (1) [t0].[Id]
FROM [age_Centers] AS [t0]

*请注意,Take(1)枚举并返回IQueryable

答案 1 :(得分:5)

将DataContext Log属性重定向到文本文件的Console.Out,并查看每个选项产生的查询。

答案 2 :(得分:2)

**First()** operates on a collection of any number of objects and returns the first object.        **Take(1)** operates on a collection of any number of objects and returns a collection containing the first object.

您也可以使用Single      Single()对一个对象的集合进行操作,只返回该对象。

答案 3 :(得分:1)

.First()如何运作:

  

如果集合是IList类型,则第一个元素由索引位置访问,该位置根据集合实现而不同。否则,迭代器返回第一个元素。

.Take(int count)总是迭代。

如果有任何增益,如果集合实现IList并且通过索引访问第一个元素的速度高于返回迭代器的速度,则会发生这种情况。我不相信这会很重要。 ;)

来源:

http://www.hookedonlinq.com/FirstOperator.ashx

http://www.hookedonlinq.com/TakeOperator.ashx

答案 4 :(得分:1)

首先会查询Take 1,因此查询没有区别。调用FirstOrDefault将是一步声明,因为Take返回IEnumerable,你还需要调用First。

首先会抛出异常,因此始终首选FirstOrDefault。

当然,编写EF查询转换器的人非常聪明,可以调用Take 1而不是执行整个结果集并返回第一项。

您可以使用SQL事件探查器进行验证。