0
我在一個小的.NET 4.5,MVC4,EF5項目上使用了存儲庫模式。存儲庫模式和IQueryable <>生成不好的SQL
我注意到,如果我改變了從存儲庫傳遞的IQueryable對象的結果,生成的SQL並不理想。
例如,在我的倉庫:
public IQueryable<Entry> GetEntries()
{
// (db is an instance of the data context)
return db.Entries.Where(e => e.UserId == WebSecurity.CurrentUserId);
}
在我的控制器,我限制行的金額退回,並對其進行排序:
public ActionResult Index()
{
// (repo is an instance of the repository object)
var entries = repo.GetEntries().Take(10).OrderByDescending(o => o.Created)
return View(entries);
}
這將生成以下SQL:
DECLARE @p__linq__0 int = 1
SELECT
[Project1].[UserId] AS [UserId],
[Project1].[Id] AS [Id],
[Project1].[Created] AS [Created],
[Project1].[LastModified] AS [LastModified],
[Project1].[BodyOriginal] AS [BodyOriginal],
[Project1].[BodyFormatted] AS [BodyFormatted],
[Project1].[FormatterVersion] AS [FormatterVersion],
[Project1].[BodyDigest] AS [BodyDigest],
[Project1].[FollowupId] AS [FollowupId],
[Project1].[AddMethod] AS [AddMethod],
[Project1].[Entry_Id] AS [Entry_Id]
FROM (SELECT
[Extent1].[Id] AS [Id],
[Extent1].[UserId] AS [UserId],
[Extent1].[Created] AS [Created],
[Extent1].[LastModified] AS [LastModified],
[Extent1].[BodyOriginal] AS [BodyOriginal],
[Extent1].[BodyFormatted] AS [BodyFormatted],
[Extent1].[FormatterVersion] AS [FormatterVersion],
[Extent1].[BodyDigest] AS [BodyDigest],
[Extent1].[FollowupId] AS [FollowupId],
[Extent1].[AddMethod] AS [AddMethod],
[Extent1].[Entry_Id] AS [Entry_Id]
FROM [dbo].[Entries] AS [Extent1]
WHERE [Extent1].[UserId] = @p__linq__0
) AS [Project1]
ORDER BY [Project1].[Created] DESC
如您所見,生成的SQL高度冗餘。
如果我修改資料庫的方法包括截斷和排序結果:
public IQueryable<Entry> GetEntries()
{
// (db is an instance of the data context)
return db.Entries.Where(e => e.UserId == WebSecurity.CurrentUserId).Take(10).OrderByDescending(o => o.Created);
}
生成的SQL是更好:
DECLARE @p__linq__0 int = 1
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[UserId] AS [UserId],
[Extent1].[Created] AS [Created],
[Extent1].[LastModified] AS [LastModified],
[Extent1].[BodyOriginal] AS [BodyOriginal],
[Extent1].[BodyFormatted] AS [BodyFormatted],
[Extent1].[FormatterVersion] AS [FormatterVersion],
[Extent1].[BodyDigest] AS [BodyDigest],
[Extent1].[FollowupId] AS [FollowupId],
[Extent1].[AddMethod] AS [AddMethod],
[Extent1].[Entry_Id] AS [Entry_Id]
FROM [dbo].[Entries] AS [Extent1]
WHERE [Extent1].[UserId] = @p__linq__0
ORDER BY [Extent1].[Created] DESC
如何克服這個問題,那就是使用存儲庫模式,同時仍然可以靈活地修改存儲庫的結果而不會創建構造不佳的SQL?
在這種情況下,冗餘不會影響性能。 – usr
我不認爲你顯示了相同的查詢。注意第二個查詢沒有Order by子句。這似乎表明它實際上並沒有做同樣的事情。 –
如果它們是相同的,那麼這意味着Linq可能通過在內存中而不是在SQL中執行Take和OrderBy來優化第二個查詢,這可能是因爲它可以「看到」更多的內容。儘管我不能某些。 –