2013-02-06 17 views
2

工作,我有幾個疑問,看起來像下面的兩個例子:一個簡單的Where子句停在EF5

// Example 1: 
var dataSeries = (from d in DataSeries 
        where d.Symbol == symbol 
        select d).FirstOrDefault(); 

// Example 2: 
return Markets.Where(m => m.DataSeries == dataSeries).ToArray(); 

,直到我遇到了哪些工作就好了「從數據庫更新模型...」。現在,我得到一個NotSupportedException:

無法創建類型爲 'MyTest.Symbol'的常量值。在此上下文中僅支持基本類型或枚舉 類型。

是的,我驗證了符號和d。 符號(和m。DataSeriesdataSeries)具有相同的類型。

是的,我可以改變我的查詢中使用的P/F鍵的關係,像這樣:

var dataSeries = (from d in DataSeries 
        where d.Symbol.Id == symbol.Id 
        select d).FirstOrDefault(); 

但我真的不希望有改變我的所有代碼到P/F鍵時關係對象關係工作得很好。

問:如何讓我的第一個示例再次運行?

+0

我不知道如何獲得的第一個例子具體工作,但我認爲你的應用程序花費大量時間進行不必要的比較。我相信,唯一需要做的比較是關鍵關係,應該更快。 – IronMan84

+0

我認爲你必須把你的查詢從'linq到entities'到'linq to objects'。您可以通過從DataSeries.ToList()中選擇來完成此操作。希望表DataSeries不是太大。原因是數據庫服務器不知道類型。我感到驚訝的是,它似乎以前工作! – tschmit007

回答

2

您不能在LINQ查詢中寫入where子句,該查詢是針對數據庫執行的。請記住,代碼將被轉換爲SQL並且將在數據庫引擎上運行。

因此,對於第一個示例,Entity Framework如何知道如何比較複雜類型MyTest.Symbol的兩個實例? EF完全不能,因爲沒有適合這種比較的SQL。

必須在where條款的東西,數據庫引擎就會明白,這將主要是基於一個ID在原始類型SQL WHERE子句指定(intbigint,...)。

使用.ToList()可以獲取從數據庫中的所有數據,並應用在內存中的結果列表中的where條款,所以where條款不會有被翻譯成SQL:

Markets.ToList().Where(m => m.DataSeries == dataSeries); 

但是你將失去數據庫服務器的所有好處:內存的巨大使用(一切都在上下文中加載),性能差......等等。

你真的應該執行where對數據庫,這意味着你將不得不使用基本類型的比較:

Markets.Where(m => m.DataSeries.ID == dataSeries.ID); 
+0

你說得對。但是這實際上只是一個EF限制,因爲實體對象不能像謂詞那樣使用。例如,在linq-to-sql和NHibernate中是可能的。 EF有可能從作爲其概念模型一部分的對象獲取原始鍵值並將其轉換爲SQL。這只是沒有實現(還?)。 –

+0

@ IranMan84 - 在我更新模型之前,代碼再次運行得很完美。 EF(如Arnold所述)應該能夠做到這一點,因爲要查找給定類型的主鍵並不難,並且將查詢從obj1 == obj2替換爲obj1.Id == obj2.Id.其他人可以做到這一點,看起來EF5在某一點上是這樣做的,因此,我希望功能上「重新開啓」。 – Kaboo

+0

我所看到的就好像EF失去了與主鍵關聯的屬性,因此無法將對象與身份比較操作進行比較,從而觸發異常。 – Kaboo

1

您的示例將不起作用,因爲EF不支持LINQ查詢中的對象比較,它不知道如何將其轉換爲SQL語句。

即使你獲取所有DataSeries到內存中首先使用DataSeries.ToList(),比較d.Symbol ==符號仍然無法工作,除非符號屬於加載列表,或者你必須重寫平等法。這是因爲默認情況下,只有當它們引用同一個實例時,兩個對象才相等。