今天我發現Entity Framework正在爲它生成的SQL添加一個不必要的子查詢。我開始挖掘我的代碼,試圖縮小它可能來自哪裏。 (很長),後來我指出了造成它的原因。但是現在我比開始時更困惑,因爲我不知道爲什麼會導致它。EF 4.1:爲什麼將常量變成變量會導致額外的子查詢?
基本上我發現,在某些情況下,只需將常量轉換爲變量就可以改變實體框架生成的SQL。我已經縮水一切到最低限度,並在一個小控制檯應用程序包裝它:
using System;
using System.Data.Entity;
using System.Linq;
class Program
{
private static readonly BlogContext _db = new BlogContext();
static void Main(string[] args)
{
const string email = "[email protected]";
var comments = from c in _db.Comments
where c.Email == email
select c;
var result = (from p in _db.Posts
join c in comments on p.PostId equals c.PostId
orderby p.Title
select new { p.Title, c.Content });
Console.WriteLine(result);
}
}
public class BlogContext : DbContext
{
public DbSet<Post> Posts { get; set; }
public DbSet<Comment> Comments { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
}
public class Comment
{
public int CommentId { get; set; }
public int PostId { get; set; }
public string Email { get; set; }
public string Content { get; set; }
}
這說明下面的輸出,這是完美的:
SELECT
[Extent1].[PostId] AS [PostId],
[Extent1].[Title] AS [Title],
[Extent2].[Content] AS [Content]
FROM [dbo].[Posts] AS [Extent1]
INNER JOIN [dbo].[Comments] AS [Extent2] ON [Extent1].[PostId] = [Extent2].[PostId]
WHERE N'[email protected]' = [Extent2].[Email]
ORDER BY [Extent1].[Title] ASC
現在,如果我做email
一個變量:
/*const*/ string email = "[email protected]";
輸出變化根本:
SELECT
[Project1].[PostId] AS [PostId],
[Project1].[Title] AS [Title],
[Project1].[Content] AS [Content]
FROM (SELECT
[Extent1].[PostId] AS [PostId],
[Extent1].[Title] AS [Title],
[Extent2].[Content] AS [Content]
FROM [dbo].[Posts] AS [Extent1]
INNER JOIN [dbo].[Comments] AS [Extent2] ON [Extent1].[PostId] = [Extent2].[PostId]
WHERE [Extent2].[Email] = @p__linq__0
) AS [Project1]
ORDER BY [Project1].[Title] ASC
請注意,LINQ to SQL似乎沒有這樣做。我知道忽略這個可能是可以的,因爲兩個命令都返回相同的數據。但我非常好奇爲什麼會發生這種情況。直到今天,我總是有(也許是錯誤的)印象,即把常量變成變量總是安全的,只要值保持不變(在這種情況下)。所以我必須問...
爲什麼一個看似微不足道的變化會在生成的SQL中造成如此大的差異?
更新:
只是要清楚,我的問題是不是email
是第一個查詢和硬編碼值在第二(可變的,這使得所有的檢測值在世界上)。我的問題是關於爲什麼變量版本導致額外的子查詢。
謝謝!
我不擔心查詢的*形式* SQL的意思是關於表達你想要的結果,而不是實現它們的過程 - 而且如果有很多或任何差異,我會感到驚訝在查詢計劃中。優化器應該產生很多相同的查詢計劃。 – 2011-05-07 16:03:28
這是一個迷人的發現!僅僅因爲這個原因Upvoted! – 2015-04-18 20:00:34