2012-06-05 134 views
0
results = (from r in results 
where r.Buildings.Any(x=>x.StructuralElements.Any(s=>s.VALUE == Model.Bedrooms.ToString() && s.CATEGORY=="RM")) 
select r); 

我想我在這裏缺少連接。但也許它們是隱含的?執行遇到這麼久,我不能做一個表來評估生成的查詢表達式使用linq指定子查詢子查詢的正確方法

+0

「results =(from r in results」呃,讓我們看看以前的查詢部分 –

回答

0

此查詢中最大的問題是這樣的:

[email protected] = Models.Bedrooms.ToString() 
[email protected] = "RM" 
SELECT * FROM Results r WHERE EXISTS 
    (SELECT x.* FROM Results tr JOIN Buildings x ON tr.SomeID=x.SomeID WHERE tr.ID = r.ID AND EXISTS 
     (SELECT s.* FROM StructuralElements s JOIN Buildings tx ON tx.OtherID = s.OtherID WHERE tx.ID=x.ID AND s.VALUE = @p1 AND s.Category = @p2)) 

你明白爲什麼這會是壞?對於每個Result,你都運行一個子查詢(它本身正在運行一個子查詢)。由於這些嵌套的子查詢,當您開始在根級別(結果和建築物)添加事物時,這將成爲時間/處理的指數增長。您最好的選擇是在完成後使用連接並獲取不同的r值。在SQL想是這樣的:

SELECT DISTINCT 
    r.* 
FROM 
    Results r 
    INNER JOIN Buildings x ON x.SomeID = r.SomeID 
    INNER JOIN StructuralElements s ON s.OtherID = r.OtherID 
WHERE 
    s.VALUE = @p1 AND s.CATEGORY = @p2 

這將工作的原因是,當你加入,如果有一個以上的加盟回來,它會複製原始行。下圖顯示了

IDs 
R  X  S 
1  -  - 
Join X 
1  1  - 
1  2  - 
1  3  - 
Join S 
1  1  1 
1  1  2 
1  2  5 
1  2  6 

假設S=2S=6滿足條件,那麼它會返回(在R,X,S形式)行1,1,21,2,6。在這種情況下獲取截然不同的r將只返回R=1,這正是您要完成的。使用EF的關係已經存在,所以你不需要做任何額外的東西,只是引用你想過濾的列:

results = (from r in results 
      from x in r.Buildings 
      from s in x.StructuralElements 
      where s.VALUE == Model.Bedrooms.ToString() && s.CATEGORY=="RM" 
      select r).Distinct(); 

這是在發揮運營商的SelectMany(這需要一個集合並將子集收集到一個集合中)。

+0

你似乎已經明白我在問什麼了,我以爲EF會處理很多煩瑣的工作,讓我測試一下 –

+0

沒問題,如果關係設置不正確,那麼'SelectMany'最終會成爲查詢世界中的'FROM TableA,TableB',這就是爲什麼EF(和L2S)處理關係你將會把這些引用轉換成連接。一般來說,當我處理嵌套關係時(甚至在SQL世界中),我會說盡量遠離'Any'。 – SPFiredrake

+0

我不知道我在做什麼。:\ –