46

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

我已经阅读了许多建议使用.Take(1)
我正在审查的代码使用的帖子.First()

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

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

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

4

5 回答 5

82

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.

于 2012-05-04T20:19:40.393 回答
5

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

于 2012-05-04T20:07:42.910 回答
2

工作原理.First()

如果集合是 IList 类型,则通过索引位置访问第一个元素,这取决于集合实现。否则,迭代器返回第一个元素。

并且.Take(int count)总是迭代。

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

资料来源:

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

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

于 2012-05-04T20:16:07.180 回答
1

首先会查询Take 1,所以查询没有区别。调用 FirstOrDefault 将是一步语句,因为 Take 返回 IEnumerable 你是否需要调用 First。

First 会抛出异常,所以 FirstOrDefault 总是首选。

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

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

于 2012-05-04T20:21:06.503 回答
1
**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()对仅包含一个对象的集合进行操作并简单地返回该对象。

于 2014-11-05T14:09:54.493 回答