C# 使用linq指定子查询的子查询的正确方法
我想我错过了这里的连接。但也许它们是暗示的?执行时间太长,我无法观察以计算生成的查询表达式此查询中最大的问题是:C# 使用linq指定子查询的子查询的正确方法,c#,linq,entity-framework,C#,Linq,Entity Framework,我想我错过了这里的连接。但也许它们是暗示的?执行时间太长,我无法观察以计算生成的查询表达式此查询中最大的问题是: results = (from r in results where r.Buildings.Any(x=>x.StructuralElements.Any(s=>s.VALUE == Model.Bedrooms.ToString() && s.CATEGORY=="RM")) select r); 你明白为什么这会很糟糕吗?对于每个结果,都运行一个
results = (from r in results
where r.Buildings.Any(x=>x.StructuralElements.Any(s=>s.VALUE == Model.Bedrooms.ToString() && s.CATEGORY=="RM"))
select r);
你明白为什么这会很糟糕吗?对于每个结果,都运行一个子查询,而子查询本身就是在运行一个子查询。由于这些嵌套的子查询,当您开始在根级别、结果和建筑物添加内容时,时间/处理将呈指数级增长。最好的办法是使用联接,并在完成后获得不同的r值。SQL希望如下所示:
--@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))
这将起作用的原因是,当您加入时,如果有多个要重新加入,它将复制原始行。下图显示了
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
假设S=2和S=6满足您的条件,那么它将以R、X、S的形式返回第1、1、2和1、2、6行。在本例中,仅获取不同的r只会返回r=1,这是您试图实现的。使用EF,这些关系已经存在,因此您不需要做任何额外的事情,只需引用您试图筛选的列:
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
这是SelectMany操作符,它使用一个集合并将子集合展平到单个集合中 results=来自results中的r,呃,向我们展示之前查询的部分。您似乎已经理解了我的问题。我以为EF会处理很多繁重的工作。让我测试一下,然后再给你回复。没问题。如果关系设置不正确,那么SelectMany最终将来自查询世界中的TableA、TableB。这就是为什么EF和L2S为您处理关系,并将这些引用转换为联接。一般来说,我会说,即使在SQL世界中处理嵌套关系时,也要尽量远离任何嵌套关系。我不知道自己在做什么\好的,这很有效。如果我将表达式查询复制到T-SQL中,它将返回预期的行数,但在应用程序中,它每次返回0行。我想我必须提出另一个问题。在再次开始对结果进行查询之前,确保结果中确实包含数据。更有可能的是,这就是正在发生的事情。如果您想要新的数据,那么只需确保执行context.Set即可获取对结果实体的引用。
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();