2011-10-19 50 views
0

我在查看執行簡單選擇查詢時生成的SQL。我首先使用來自nuget的示例博客上下文代碼。在select子句中使用方法時的Enitity框架性能

如果以下運行:

BlogContext _context = new BlogContext(); 
var comments = _context.Comments.Select(c => new CommentReadOnly {Author = c.Author}); 
var count = comments.Count(); 

下面的SQL中產生:當計數在預計的SQL執行

SELECT 
    [GroupBy1].[A1] AS [C1] 
FROM (SELECT 
    COUNT(1) AS [A1] 
    FROM [dbo].[Comments] AS [Extent1] 
) AS [GroupBy1] 

但是如果我修改代碼,如下所示:

BlogContext _context = new BlogContext(); 
var comments = _context.Comments.Select(c => new CommentReadOnly {Author = c.Author}); 
var count = comments.Count(); 

private CommentReadOnly ToCommentReadOnly(Comment comment) 
{ 
    return new CommentReadOnly 
    { 
    Author = comment.Author, 
    }; 
} 

下面的SQL中產生:

SELECT 
[Extent1].[ID] AS [ID], 
[Extent1].[PostID] AS [PostID], 
[Extent1].[Text] AS [Text], 
[Extent1].[Author] AS [Author] 
FROM [dbo].[Comments] AS [Extent1] 

隨着count在代碼完成。

原因(我認爲)是因爲第一個返回爲IQueryable,其中第二個是IEnumerable

是否有可能返回第二個查詢爲IQueryable而不執行SQL?

我問的原因是我創建了一個通用的存儲庫層,可以查詢我的實體並將它們轉換爲所需的類型(在上面的示例中可能有幾個不同的只讀對象)。我不希望SQL執行得如此早,因爲可能會在不同情況下進行分頁或進行其他過濾。

+0

這兩個代碼片段是不是完全相同?查詢使用'.Count()'執行,我發現'.Count()'之前的代碼沒有區別。 – Slauma

回答

0

我在這兩個查詢中看不到任何區別。但是,我想你想要返回一個IQueryable對象到客戶端,以便客戶端可以執行進一步的過濾並從那裏獲取計數。

您可以簡單地返回對象而不進行選擇,然後讓客戶端完成剩下的工作。

return _context.Comments 

客戶可以在此IQueryable的對象

0

我想在你的第二個查詢您執行功能ToCommentReadOnly()執行額外的過濾所以這不能在SQL完全完成,你結束了一個Linq To Objects(IEnumerable)。

但是你聲明你想從你的Repository中返回一個IQueryable。這不是推薦的做法!訪問數據的代碼應該隱藏在你的倉庫中,否則你會遇到問題。

舉例來說,您的存儲庫(封裝了您的ObjectContext)超出了範圍,之後您會嘗試枚舉存儲庫爲您提供的IQueryable結果。這將拋出一個錯誤,因爲IQueryable不能再被執行。

如果您從存儲庫中公開了IQueryable,那麼您可以爲存儲庫的最終用戶提供他們想要構建自己的查詢所需的全部自由權,這是您希望通過添加存儲庫避免的事情!

因此從您的Repository返回一個IEnumerable是件好事:)

+0

我不會同意暴露'IQueryable'和存儲庫之外的上下文引用通常是*「不是推薦的做法」。有許多理由贊成這樣做(簡單,直接投影到ViewModels,處理桌面應用程序中的大數據和數據虛擬化,延遲加載等),與此相反。 – Slauma

+0

一個例子是當你試圖優化你的查詢。在我們的倉庫中,我們使用CompiledQueries來提高性能。如果我們公開IQueryable而不是IEnumerable,那麼如果存儲庫的用戶會改變查詢並使用預編譯,則編譯將毫無用處。通過使用IQueryable,您還可以將您的代碼耦合到實體框架。 Repository模式的整個想法是獨立於你的持久機制。我們從適合上層需求的數據層中公開POCO或定製的DTO。 –

+0

我知道:)這些都是好點,理論總是聽起來不錯。但是,在「持久性機制的獨立性」和數據訪問的封裝方面,很少提及實踐中(時間和開發工作)的*成本*。不要誤解我,我並不是說你的觀點是不正確的,但我不同意觀點總是正確的。 – Slauma