2011-11-25 34 views
0

我使用asp.net 4 c#和ef4。EF預編譯查詢並返回標量值

我有這段代碼,它應該編譯查詢並返回一個標量值(我使用匿名類型)。

我的代碼沒有明顯的錯誤,但是因爲是我第一次編寫一個編譯查詢,我想知道是寫得好還是可以提高性能。

var query = CompiledQuery.Compile((CmsConnectionStringEntityDataModel ctx) 
         => from o in ctx.CmsOptions 
          where o.OptionId == 7 
          select new 
          { 
           Value = o.Value 
          }); 

        uxHtmlHead.Text = query(context).FirstOrDefault().Value;// I print the result in a Label 

SQL配置文件輸出:

SELECT TOP (1) 
[Extent1].[OptionId] AS [OptionId], 
[Extent1].[Value] AS [Value] 
FROM [dbo].[CmsOptions] AS [Extent1] 
WHERE 7 = [Extent1].[OptionId] 

非常感謝

後沃特建議

結果(請傢伙有再次仔細檢查):

 static readonly Func<CmsConnectionStringEntityDataModel, int, string> compiledQueryHtmlHead = 
    CompiledQuery.Compile<CmsConnectionStringEntityDataModel, int, string>(
      (ctx, id) => ctx.CmsOptions.FirstOrDefault(o => o.OptionId == id).Value); 


using (var context = new CmsConnectionStringEntityDataModel()) 
      { 
       int id = 7; 
       uxHtmlHead.Text = compiledQueryHtmlHead.Invoke(context, id); 
      } 

生成的SQL(我不明白爲什麼有LEFT JOIN)

exec sp_executesql N'SELECT 
[Project1].[Value] AS [Value] 
FROM (SELECT 1 AS X) AS [SingleRowTable1] 
LEFT OUTER JOIN (SELECT 
    [Extent1].[Value] AS [Value] 
    FROM [dbo].[CmsOptions] AS [Extent1] 
    WHERE [Extent1].[OptionId] = @p__linq__0) AS [Project1] ON 1 = 1',N'@p__linq__0 int',@p__linq__0=7 

回答

2

有兩件事情可以改善的。

首先,預編譯查詢絕對是一個好主意,但如果你看看你的代碼,你會看到它預編譯查詢每一次而不是一次。

您需要將預編譯查詢移至僅初始化一次的靜態變量。

另一件需要注意的事情是,在預編譯查詢時,在執行查詢之前不應再修改查詢。

您正在構建一個預編譯查詢,它將選擇所有行,然後說'firstordefault',它將預編譯查詢更改爲SELECT TOP(1),並且您失去了預編譯的好處。您需要將FirstOrDefault部分移到預編譯查詢中,並只返回一個結果。請參考this文檔如果你看看例子,你可以看到他們如何使用一個靜態字段來保存已編譯的查詢以及它們如何指定返回值。

+0

再次感謝Wouter的支持! – GibboK

+0

你能發佈結果代碼嗎?會很好的爲其他:) –

+0

代碼發佈:-),請Wouter看看現在是否更有意義。我使用了Func,並在方法中包含了FirstOrDefault。我唯一不理解的是Sql中的LEFT OUTER JOIN。你有好主意嗎?非常感謝您的幫助! – GibboK