2011-06-05 58 views
4

我有兩行代碼,一個是選擇不上IQueryable的工作,但確實在IList的

AllItems().Where(c => c.Id== id) 
      .Select(d => new Quality(d.QualityType)).ToList(); 

,另一個

AllItems().Where(c => c.Id== id).ToList() 
      .Select(d => new Quality(d.QualityType)).ToList(); 

唯一的區別就是在第二條語句ToList()Where聲明後調用。第二個聲明很好。

在第一個語句中,默認的無參數構造函數被命中,而不是帶有參數的構造函數。因此該列表已創建,但列表中的對象已使用默認值進行初始化,而不是使用d.QualityType進行初始化。

你可以看到有問題的文件的完整源在(方法:GetBestQualityInHistory)

https://github.com/kayone/NzbDrone/blob/master/NzbDrone.Core/Providers/HistoryProvider.cs

**編輯:經過進一步調查,這似乎是一個亞音速的bug,如果最後ToList被替換爲OrderBy亞音速拋出The construtor 'Void .ctor(NzbDrone.Core.Repository.Quality.QualityTypes, Boolean)' is not supported

+0

你在這裏調用了'ToList' * both * cases,但是在第二種情況下,你調用它*兩次*。爲什麼? – 2011-06-05 19:28:25

+0

對不起,這只是錯誤複製過去 – 2011-06-05 19:29:02

+0

AllItems是什麼類型?它只是一個內存列表,或者它是通過例如持久性框架提供給您的東西嗎? 可能是相關的,因爲如果不使用ToList,持久性框架將處理呼叫。據我所知.net在tolist後處理它(因爲它是一個列表之後) – thekip 2011-06-05 19:31:44

回答

4

如果SubSonic以與Entity框架相同的方式工作,您不能使用帶參數的構造函數 - 您必須使用無參數的構造函數和初始化函數。我非常高層次的解釋是,查詢沒有按原樣執行 - 它被轉換爲SQL,因此您必須使用屬性初始值設定項,以便表達式樹知道投影類型中的哪些屬性應該由值填充。當使用帶參數的構造函數時,表達式樹不知道傳入的參數屬於哪裏(它不檢查構造函數的內容)。一旦執行Tolist並將結果集實現爲QuantityType實例,就會調用真正的構造函數(無參數)。

+0

代碼最初使用了初始化器,我將其更改爲構造函數以追蹤問題。 – 2011-06-05 19:54:39

+0

神聖的包裝。我剛剛在EF 3.5中測試了參數化構造函數的用法,並且我希望你錯了......但是,你是對的。我感到眼花繚亂。 EF會拋出一個「LINQ to Entities支持只有無參數的構造函數和初始化器」。例外。 EF 4.0中仍然如此?我一直在用LINQ to SQL來做這件事。 – Steven 2011-06-05 20:08:23

+0

@Steven:是的,它在EFv4中是一樣的,根據這一點,它應該在Linq-to-sql中也是一樣的,但我沒有自己嘗試。 – 2011-06-05 20:28:05

0

這不是一個真正的答案,我打算將它作爲評論,但需要更多的代碼片段空間。

通過SubSonic代碼判斷,我敢肯定,在某些情況下,如果您得到「構造函數不支持」的錯誤,SS出於某種原因試圖將您的new ...()語句解析爲SQL。該問題的方法是SQL格式化的一部分,看起來像它只能處理日期時間:

protected override NewExpression VisitNew(NewExpression nex) 
    { 
     if (nex.Constructor.DeclaringType == typeof(DateTime)) 
     { 
      // ...omitted for brevity... 
     } 
     throw new NotSupportedException(string.Format("The construtor '{0}' is not supported", nex.Constructor)); 
    } 

我認爲,如果你不喜歡的東西,通常會被擊中:

someData 。哪裏(數據=> data.CreatedDate < = new DateTime(2011,12,01)) .Select(data => data)

然後,newDateTime將被轉換爲SQL。 所以,不管你如何改變Linq來獲得這個異常,我認爲這就是發生了什麼。 我認爲這是因爲如果您在.Select()之後添加.OrderBy()那麼您不再調用AllItems()返回的IQueryable上的OrderBy,而是嘗試按.Select()返回的內容排序,這是新的質量對象的枚舉,所以SS可能會試圖將所有這些轉換爲SQL。

我想知道如果它能正常工作,如果你扭轉它?

AllItems().Where(c => c.Id== id) 
     .OrderBy(d => d.QualityType) 
     .Select(d => new Quality(d.QualityType)); 
相關問題