我正在尝试将这段非常简单的 SQL 转换为 LINQ:
select * from Projects p
inner join Documents d
on p.ProjectID = d.ProjectID
left join Revisions r
on r.DocumentID = d.DocumentID
and r.RevisionID IN (SELECT max(r2.RevisionID) FROM Revisions r2 GROUP BY r2.DocumentID)
WHERE p.ProjectID = 21 -- Query string in code
这表示,如果文档存在任何修订,请返回最高修订 ID。由于它是左连接,如果不存在修订,我仍然希望返回结果。
这按预期工作,显示存在的任何修订(并返回最高修订 ID),所有没有任何修订的文档也是如此。
尝试使用 LINQ 编写此内容时,我只得到文档存在修订的结果。
到目前为止,这是我的尝试:
var query = from p in db.Projects
join d in db.Documents on new { ProjectID = p.ProjectID } equals new { ProjectID = Convert.ToInt32(d.ProjectID) }
join r in db.Revisions on new { DocumentID = d.DocumentID } equals new { DocumentID = Convert.ToInt32(r.DocumentID) } into r_join
from r in r_join.DefaultIfEmpty()
where
(from r2 in db.Revisions
group r2 by new { r2.DocumentID }
into g
select new { MaxRevisionID = g.Max(x => x.RevisionID) }).Contains(
new { MaxRevisionID = r.RevisionID }) &&
p.ProjectID == Convert.ToInt32(Request.QueryString["projectId"])
select new { d.DocumentID, d.DocumentNumber, d.DocumentTitle, RevisionNumber = r.RevisionNumber ?? "<No rev>", Status = r.DocumentStatuse == null ? "<Not set>" : r.DocumentStatuse.Status };
我不太擅长 LINQ,一直在使用转换器“Linqer”来帮助我,但是在尝试时我收到以下消息:
“SQL 无法转换为 LINQ:只能使用 JOIN 表达式中的“=”运算符。“IN”运算符无法转换。”
你会看到我.DefaultIfEmpty()
在修订表上。如果我删除了where (
进行分组的代码,无论文档是否存在修订,我都会得到所需的结果。但是如果有链接,where 子句应该返回文档的最高修订号,如果没有,我仍然想返回所有其他数据。与我的 SQL 代码不同,这不会发生。它只返回有指向修订表链接的数据。
我希望这有点道理。按代码分组是什么弄乱了我的结果集。无论是否有指向修订表的链接,我仍然希望返回我的结果。请帮忙!
谢谢。
=======
感谢 Gert,我现在使用的代码。
var query = from p in db.Projects
from d in p.Documents
where p.ProjectID == Convert.ToInt32(Request.QueryString["projectId"])
select new
{
p.ProjectID,
d.DocumentNumber,
d.DocumentID,
d.DocumentTitle,
Status = d.Revisions
.OrderByDescending(rn => rn.RevisionID)
.FirstOrDefault().DocumentStatuse.Status,
RevisionNumber = d.Revisions
.OrderByDescending(rn => rn.RevisionID)
.FirstOrDefault().RevisionNumber
};
gvDocumentSelection.DataSource = query;
gvDocumentSelection.DataBind();
虽然这可行,但您会看到我通过运行相同的代码从修订表中选择了两个字段,但选择了两个不同的字段。我猜有更好,更有效的方法来做到这一点?理想情况下,我想加入修订表,以防我需要访问更多字段,但随后我又遇到了相同的分组问题。
Status = d.Revisions
.OrderByDescending(rn => rn.RevisionID)
.FirstOrDefault().DocumentStatuse.Status,
RevisionNumber = d.Revisions
.OrderByDescending(rn => rn.RevisionID)
.FirstOrDefault().RevisionNumber
最终工作代码:
var query = from p in db.Projects
from d in p.Documents
where p.ProjectID == Convert.ToInt32(Request.QueryString["projectId"])
select new
{
p.ProjectID,
d.DocumentNumber,
d.DocumentID,
d.DocumentTitle,
LastRevision = d.Revisions
.OrderByDescending(rn => rn.RevisionID)
.FirstOrDefault()
};
var results = from x in query
select
new
{
x.ProjectID,
x.DocumentNumber,
x.DocumentID,
x.DocumentTitle,
x.LastRevision.RevisionNumber,
x.LastRevision.DocumentStatuse.Status
};
gvDocumentSelection.DataSource = results;
gvDocumentSelection.DataBind();