2012-08-07 4 views
30

Je me sers EF4.0, et moi avons écrit une requête:Pourquoi SingleOrDefault résulte TOP (2) en SQL?

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

je besoin que d'un poste de cette requête. Je pensais que SingleOrDefault() va générer "SELECT TOP (1) ...", mais quand je regarde dans SQL Profiler, il a été:

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' 

Je me demande pourquoi résultat EF SELECT TOP (2)? J'ai seulement besoin d'un message.

+2

Et vous pouvez utiliser: 'var query = context.Post.SingleOrDefault (p => p.Id == postId);' – Malmi

+0

Nous utilisons NHibernate, ce que je m'attendais à faire, mais ce n'est pas ... Il sélectionne tout ... Grrrrr ... –

Répondre

48

Il sélectionne le top 2 de sorte que s'il existe réellement 2 ou plus de 2 enregistrements dans la base de données, une exception est levée. Si elle ne sélectionne que le top 1, il n'y aurait aucun moyen d'erreur.

17

En demandant la SingleOrDefault d'une séquence, vous demandez ce comportement:

  • si la séquence a exactement 0 éléments, retourner le default pour le type
  • élément de la séquence si la séquence a exactement 1 élément, l'élément de retour
  • si la séquence a plus d'élément 1, jeter

Faire un TOP (1) habiliterait les deux premières parties de ceci, mais pas le troisième. Seulement en faisant un TOP (2) pouvons-nous différencier exactement entre 1 record et plus de 1 record.

Si vous ne voulez pas voulez ou avez besoin de la troisième partie de la remarque ci-dessus, utilisez plutôt FirstOrDefault.