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);

我想我在这里缺少连接。但也许它们是隐含的?执行运行时间太长,我无法监视来评估生成的查询表达式

4

1 回答 1

0

此查询中最大的问题是:

--@p1 = Models.Bedrooms.ToString()
--@p2 = "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))

你明白为什么这会很糟糕吗?对于每个结果,您都在运行一个子查询(它本身正在运行一个子查询)。由于这些嵌套的子查询,当您开始在根级别(结果和建筑物)添加内容时,时间/处理将呈指数增长。最好的办法是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. 在这种情况下,仅获得 distinctr只会返回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 运算符(它接受一个集合并将子集合扁平化为一个集合)。

于 2012-06-05T14:43:04.210 回答