NHibernate linq fetch query across multiple joins with subquery causes incorrect sql
NHibernate linq fetch query across multiple joins with subquery causes incorrect sql
我在 sql 服务器数据库中有四个表:
Part
-----
Id (PK)
LineId (FK)
other fields...
Line
-----
Id (PK)
ProcessId (FK)
other fields...
Process
-----
Id (PK)
ProcessTypeId (FK)
other fields...
ProcessType
-----
Id (PK)
other fields...
我正在尝试使用带提取功能的 linq 查询来混合这些实体,然后将结果映射到视图模型 dto。
我正在使用两个查询,一个在 Part
上,我正在对其应用过滤器以缩小结果范围:
var partids = s.Query<Part>()
.Where(p => p.Line.Process.ProcessType.Id == processTypeId)
.Select(p => p.Id);
然后我使用此查询预先加载相关实体并将第一个查询用作子查询:
var q = s.Query<Part>()
.Fetch(p => p.Line)
.ThenFetch(l => l.Process)
.ThenFetch(pr => pr.ProcessType)
.Where(p => partids.Contains(p.Id))
.ToList();
虽然此查询有效,但我注意到加载时间很长。因此,使用分析器,我查看了生成的 SQL 是:
SELECT part0_.Id AS Id0_0_,
line1_.Id AS Id1_1_,
process2_.Id AS Id2_2_,
process3_.Id AS Id3_3_,
part0_.Name AS Name0_0_,
part0_.LineId AS Line3_0_0_,
line1_.Name AS Name1_1_,
line1_.ProcessId AS Proccess3_1_1_,
process2_.Name AS Name2_2_,
process2_.ProcessTypeId AS Proccess3_2_2_,
process3_.Name AS Name3_3_
FROM part part0_
LEFT OUTER JOIN Line line1_ ON part0_.LineId=line1_.Id
LEFT OUTER JOIN Process process2_ ON line1_.ProcessId=process2_.Id
LEFT OUTER JOIN ProcessType process3_ ON process2_.ProcessTypeId=process3_.Id
WHERE part0_.Id IN
( SELECT part4_.Id
FROM Part Part4_
INNER JOIN Line Line5_ ON Part4_.LineId=Line5_.Id
WHERE process2_.ProcessTypeId= 126 );
在大多数情况下,子查询连接回主查询导致 运行 极其缓慢。
我原以为生成的 SQL 是这样的:
SELECT part0_.Id AS Id0_0_,
line1_.Id AS Id1_1_,
process2_.Id AS Id2_2_,
process3_.Id AS Id3_3_,
part0_.Name AS Name0_0_,
part0_.LineId AS Line3_0_0_,
line1_.Name AS Name1_1_,
line1_.ProcessId AS Proccess3_1_1_,
process2_.Name AS Name2_2_,
process2_.ProcessTypeId AS Proccess3_2_2_,
process3_.Name AS Name3_3_
FROM part part0_
LEFT OUTER JOIN Line line1_ ON part0_.LineId=line1_.Id
LEFT OUTER JOIN Process process2_ ON line1_.ProcessId=process2_.Id
LEFT OUTER JOIN ProcessType process3_ ON process2_.ProcessTypeId=process3_.Id
WHERE part0_.Id IN
( SELECT part4_.Id
FROM Part part4_
INNER JOIN Line Line5_ ON part4_.LineId=Line5_.Id
INNER JOIN Process Process6_ ON Line5_.LineId=Process6_.Id
WHERE Process6_.ProcessTypeId= 126 );
我将 NHibernate 4 与 linq 提供程序一起用于我的所有查询。我在这里的 linq 查询中遗漏了什么吗?
我目前使用的解决方法是将 partids
查询与 ToList
混合,然后使用内存中的 ID 列表。但是,如果可能的话,我想在这种情况下避免两次往返数据库。
我目前无法使用 QueryOver
或 HQL
api,因为我所有查询过滤器代码都使用 linq。
请帮忙!
很遗憾,我认为您当前使用的解决方法是您的最佳选择。
这是 NHibernate 中的一个错误,它目前影响版本 4,我很确定它也存在于 3.3 中。
错误已 reported。
我在 sql 服务器数据库中有四个表:
Part
-----
Id (PK)
LineId (FK)
other fields...
Line
-----
Id (PK)
ProcessId (FK)
other fields...
Process
-----
Id (PK)
ProcessTypeId (FK)
other fields...
ProcessType
-----
Id (PK)
other fields...
我正在尝试使用带提取功能的 linq 查询来混合这些实体,然后将结果映射到视图模型 dto。
我正在使用两个查询,一个在 Part
上,我正在对其应用过滤器以缩小结果范围:
var partids = s.Query<Part>()
.Where(p => p.Line.Process.ProcessType.Id == processTypeId)
.Select(p => p.Id);
然后我使用此查询预先加载相关实体并将第一个查询用作子查询:
var q = s.Query<Part>()
.Fetch(p => p.Line)
.ThenFetch(l => l.Process)
.ThenFetch(pr => pr.ProcessType)
.Where(p => partids.Contains(p.Id))
.ToList();
虽然此查询有效,但我注意到加载时间很长。因此,使用分析器,我查看了生成的 SQL 是:
SELECT part0_.Id AS Id0_0_,
line1_.Id AS Id1_1_,
process2_.Id AS Id2_2_,
process3_.Id AS Id3_3_,
part0_.Name AS Name0_0_,
part0_.LineId AS Line3_0_0_,
line1_.Name AS Name1_1_,
line1_.ProcessId AS Proccess3_1_1_,
process2_.Name AS Name2_2_,
process2_.ProcessTypeId AS Proccess3_2_2_,
process3_.Name AS Name3_3_
FROM part part0_
LEFT OUTER JOIN Line line1_ ON part0_.LineId=line1_.Id
LEFT OUTER JOIN Process process2_ ON line1_.ProcessId=process2_.Id
LEFT OUTER JOIN ProcessType process3_ ON process2_.ProcessTypeId=process3_.Id
WHERE part0_.Id IN
( SELECT part4_.Id
FROM Part Part4_
INNER JOIN Line Line5_ ON Part4_.LineId=Line5_.Id
WHERE process2_.ProcessTypeId= 126 );
在大多数情况下,子查询连接回主查询导致 运行 极其缓慢。
我原以为生成的 SQL 是这样的:
SELECT part0_.Id AS Id0_0_,
line1_.Id AS Id1_1_,
process2_.Id AS Id2_2_,
process3_.Id AS Id3_3_,
part0_.Name AS Name0_0_,
part0_.LineId AS Line3_0_0_,
line1_.Name AS Name1_1_,
line1_.ProcessId AS Proccess3_1_1_,
process2_.Name AS Name2_2_,
process2_.ProcessTypeId AS Proccess3_2_2_,
process3_.Name AS Name3_3_
FROM part part0_
LEFT OUTER JOIN Line line1_ ON part0_.LineId=line1_.Id
LEFT OUTER JOIN Process process2_ ON line1_.ProcessId=process2_.Id
LEFT OUTER JOIN ProcessType process3_ ON process2_.ProcessTypeId=process3_.Id
WHERE part0_.Id IN
( SELECT part4_.Id
FROM Part part4_
INNER JOIN Line Line5_ ON part4_.LineId=Line5_.Id
INNER JOIN Process Process6_ ON Line5_.LineId=Process6_.Id
WHERE Process6_.ProcessTypeId= 126 );
我将 NHibernate 4 与 linq 提供程序一起用于我的所有查询。我在这里的 linq 查询中遗漏了什么吗?
我目前使用的解决方法是将 partids
查询与 ToList
混合,然后使用内存中的 ID 列表。但是,如果可能的话,我想在这种情况下避免两次往返数据库。
我目前无法使用 QueryOver
或 HQL
api,因为我所有查询过滤器代码都使用 linq。
请帮忙!
很遗憾,我认为您当前使用的解决方法是您的最佳选择。
这是 NHibernate 中的一个错误,它目前影响版本 4,我很确定它也存在于 3.3 中。
错误已 reported。