56

我正在使用 EF4.0,我写了一个查询:

var query = context.Post.Where(p => p.Id == postId).SingleOrDefault();

我只需要此查询中的一篇文章。我认为 SingleOrDefault() 会生成“SELECT TOP(1) ...”,但是当我查看 SQL Profiler 时,它是:

exec sp_executesql N'SELECT TOP (2) 
[Extent1].[Id] AS [Id], 
[Extent1].[Title] AS [Title], 
[Extent1].[Slug] AS [Slug], 
[Extent1].[PubDate] AS [PubDate], 
[Extent1].[PostContent] AS [PostContent], 
[Extent1].[Author] AS [Author], 
[Extent1].[CommentEnabled] AS [CommentEnabled], 
[Extent1].[AttachmentId] AS [AttachmentId], 
[Extent1].[IsPublished] AS [IsPublished], 
[Extent1].[Hits] AS [Hits], 
[Extent1].[CategoryId] AS [CategoryId]
FROM [dbo].[Post] AS [Extent1]
WHERE [Extent1].[Id] = @p__linq__0',N'@p__linq__0 uniqueidentifier',@p__linq__0='ECD9F3BE-3CA9-462E-AE79-2B28C8A16E32'

我想知道为什么 EF 会导致 SELECT TOP (2)?我只需要一个帖子。

4

2 回答 2

81

它选择前 2 条,以便如果数据库中实际上有 2 条或多于 2 条记录,则会引发异常。如果它只选择前 1 名,则无法出错。

于 2012-08-07T04:11:13.387 回答
34

通过询问SingleOrDefault一个序列,你要求这种行为:

  • 如果序列正好有0元素,则返回default序列的元素类型
  • 如果序列正好有1元素,则返回元素
  • 如果序列有多个1元素,则抛出

做 aTOP (1)将授权前两部分,但不是第三部分。只有通过 a TOP (2),我们才能区分完全1记录和超过1记录。

如果您想要或不需要上述行为的第三部分,请改用FirstOrDefault.

于 2012-08-07T08:20:41.230 回答