[英]Using a delegate CompiledQuery in a join?
我有一個與我之前的問題相關的問題 。 在LINQ的現有位中涉及多個連接 ,我試圖采用包含連接的每個單獨方法並將其轉換為CompiledQuery 。
一,正常的LINQ方法:
private IQueryable<Widget> GetWidgetQuery()
{
return db.Widgets.Where(u => (!u.SomeField.HasValue || !u.SomeField.Value));
}
在這里,CompiledQuery的委托(字段)定義沿着這些方向:
private static readonly Func<DBDataContext, IQueryable<Widget>> GetWidgetQuery =
CompiledQuery.Compile((DBDataContext db) =>
db.Widgets.Where(u => (!u.SomeField.HasValue || !u.SomeField.Value)));
如果我將鼠標懸停在方法GetWidgetQuery()的正常LINQ語句上,我看到它是一個如下方法 :
(method) IQueryable<Widget> GetWidgetQuery()
但是,編譯的查詢委托( 字段 )不同如下:
(field) Func<DBDataContext, IQueryable<Widget>> GetWidgetQuery
在作為LINQ語句的一部分執行后者時,語法不同如下。 首先,正常LINQ參與加入:
var myquery =
from wxr in GetWidgetXRQuery()
join w in GetWidgetQuery() on wxr.WidgetID equals w.ID
select new DTO.WidgetList
{
...
}
在這里,以委托形式調用CompiledQuery:
var myquery =
from wxr in GetWidgetXRQuery()
join w in GetWidgetQuery.Invoke(myContext) on wxr.WidgetID equals w.ID
select new DTO.WidgetList
{
...
}
前者返回預期的結果集; 后者,當我嘗試myquery.ToList()時 ,產生一個stackoverflow異常,部分與.NET 3.5的這個限制有關 ,我想。
有人可以請幫助我理解編譯語句如何作為一個字段存在(或者我想我應該說一個委托)而不是一個方法是否會殺死我的查詢? 總之,我知道我在做什么是錯的,但我不確定我理解我誤解了什么。
我試着在EF 4上做大致相同的事情,一切似乎都很好。 所以這是一個EF 3.5問題,或者它與你的GetWidgetXRQuery
實現有關,或者兩者的某種組合。
但我想提出的真正觀點是,正如Roy Goode在回答您之前的問題時所述,一旦您以任何方式擴展該查詢,您將失去預編譯查詢的所有優勢。 通過嘗試對查詢執行加入,您將其轉換為純粹的舊查詢。 所以你不妨使用看起來適合你的非編譯版本。
意識到你在談論LINQ to SQL。 這種查詢確實似乎在Entity Framework中有支持,但在LINQ to SQL中卻沒有。 在.NET 4中,我收到以下錯誤:
不支持返回自引用常量表達式的IQueryable。
這對我來說意義不大,但我猜它與內部表示編譯查詢的方式有關。 如果我將查詢評估為變量並稍后在查詢中使用該變量,我仍會得到相同的錯誤,因此它顯然與委托和函數之間的差異無關。 我仍然認為編譯的查詢不適合在這里使用。 您需要創建一個大的編譯查詢來表示您要執行的整個查詢,或者如果您想以這種方式將它們拼湊在一起,則需要使用常規查詢。
我在進行數據庫集成測試時遇到了同樣的錯誤,直接跳到了這一點而沒有試圖解釋我的具體問題。 Linq to Sql將在使用IQueryable時在內部創建sql查詢,並且當您在該IQueryable上執行方法時,即ToList()它將在數據庫上執行該查詢。 所以在我的情況下,我加入一個返回IQueryable但被模擬返回結果的方法,它試圖將其編譯為sql查詢,但我創建的IQueryable沒有內部SQL查詢
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.