Linq2SQL 中多个连接的不正确结果
Incorrect results from multiple joins in Linq2SQL
我的任务是将一些老旧的 SQL 转换为 Linq2SQL,我知道这不应该是首选,但它需要完成。
问题
我一直在尝试强制特定连接复制所需的输出,下面是 SQL 的简化版本,其中显示了一个参数变体,然后是我在 Linq2 中尝试的简化版本SQL。表 1 中可能会查询几个替代字段,因此在转换后的代码中使用 q 和 q2,但实际参数与问题无关。
瞄准
查询需要从 Table1 中检索相关行,从 Table2 中检索最新的相关行以及从 Table2 的父级 table Table3 中检索附加数据,最好一次通过。
Table1可能有0-n个匹配项,Table1与Table2有0-n行1:n关系,Table3与Table2有1:n关系
无论我如何构建表达式,linq 都会生成一个 INNER JOIN 到 Table2 上,不包括 Table1 中的行,我如何构建 linq 查询以获得所需的结果?
SELECT [...]
FROM Table1 t1
LEFT JOIN (
SELECT MAX(id) AS id, parent_id
FROM Table2
GROUP BY parent_id
) x2 ON t1.id = x2.parent_id
LEFT JOIN Table2 t2 ON x2.id = t2.id
LEFT JOIN Table3 t3 ON t2.table3_id = t3.id
WHERE t1.id = row_id
var q = dc.Table1.AsQueryable();
q = from r in q where r.id == row_id select r;
var q2 = from r in (q)
join x2 in (from r in dc.Table2.DefaultIfEmpty() group r by r.parent_id into maxt2 let max_id = maxt2.Max(f => f.id) select new { maxt2.Key, max_id }) on r.id equals wx.Key
join t2 in dc.Table2.DefaultIfEmpty() on x2.max_id equals t2.id
join t3 in dc.Table3.DefaultIfEmpty() on t2.table3_id equals t3.id
select
{
[...]
};
这是我使用我的食谱规则进行的翻译:
var Q1 = from t2 in dc.Table2
group t2 by t2.parent_id into t2g
select new { parent_id = t2g.Key, id = t2g.Max(t2 => t2.id) };
var Q2 = from t1 in Table1
where t1.id == row_id
join q1 in Q1 on t1.id equals q1.parent_id into q1j
from q1 in q1j.DefaultIfEmpty()
join t2 in dc.Table2 on q1.id equals t2.id into t2j
from t2 in t2j.DefaultIfEmpty()
join t3 in dc.Table3 on t2.table3_id equals t3.id into t3j
from t3 in t3j.DefaultIfEmpty()
select new { t1, t2, t3 };
我的任务是将一些老旧的 SQL 转换为 Linq2SQL,我知道这不应该是首选,但它需要完成。
问题
我一直在尝试强制特定连接复制所需的输出,下面是 SQL 的简化版本,其中显示了一个参数变体,然后是我在 Linq2 中尝试的简化版本SQL。表 1 中可能会查询几个替代字段,因此在转换后的代码中使用 q 和 q2,但实际参数与问题无关。
瞄准
查询需要从 Table1 中检索相关行,从 Table2 中检索最新的相关行以及从 Table2 的父级 table Table3 中检索附加数据,最好一次通过。
Table1可能有0-n个匹配项,Table1与Table2有0-n行1:n关系,Table3与Table2有1:n关系
无论我如何构建表达式,linq 都会生成一个 INNER JOIN 到 Table2 上,不包括 Table1 中的行,我如何构建 linq 查询以获得所需的结果?
SELECT [...]
FROM Table1 t1
LEFT JOIN (
SELECT MAX(id) AS id, parent_id
FROM Table2
GROUP BY parent_id
) x2 ON t1.id = x2.parent_id
LEFT JOIN Table2 t2 ON x2.id = t2.id
LEFT JOIN Table3 t3 ON t2.table3_id = t3.id
WHERE t1.id = row_id
var q = dc.Table1.AsQueryable();
q = from r in q where r.id == row_id select r;
var q2 = from r in (q)
join x2 in (from r in dc.Table2.DefaultIfEmpty() group r by r.parent_id into maxt2 let max_id = maxt2.Max(f => f.id) select new { maxt2.Key, max_id }) on r.id equals wx.Key
join t2 in dc.Table2.DefaultIfEmpty() on x2.max_id equals t2.id
join t3 in dc.Table3.DefaultIfEmpty() on t2.table3_id equals t3.id
select
{
[...]
};
这是我使用我的食谱规则进行的翻译:
var Q1 = from t2 in dc.Table2
group t2 by t2.parent_id into t2g
select new { parent_id = t2g.Key, id = t2g.Max(t2 => t2.id) };
var Q2 = from t1 in Table1
where t1.id == row_id
join q1 in Q1 on t1.id equals q1.parent_id into q1j
from q1 in q1j.DefaultIfEmpty()
join t2 in dc.Table2 on q1.id equals t2.id into t2j
from t2 in t2j.DefaultIfEmpty()
join t3 in dc.Table3 on t2.table3_id equals t3.id into t3j
from t3 in t3j.DefaultIfEmpty()
select new { t1, t2, t3 };