我想这个很简单的一块SQL来LINQ转换:转换SQL到LINQ查询时,我不能用“IN”
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 cannot be converted to LINQ: Only "=" operator in JOIN expression can be used. "IN" operator cannot be converted."
你会在修订表上看到我有.DefaultIfEmpty()
。如果我删除执行分组的代码片段,无论文档是否存在修订,我都会得到所需的结果。但是,如果有链接,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();
感谢格特。这非常接近,非常感谢,谢谢。但是,我试图从Revisions表中选择两个字段(这就是为什么我想要连接),我还需要修订表中的状态字段。什么是完成这个最好的方法?我试过'Status = d.Revisions.Select(s => s.DocumentStatuse.Status)'但是得到一个错误:'System.Data.Linq.SqlClient.Implementation.ObjectMaterializer1 + d__01 [System.Data.SqlClient.SqlDataReader ,System.String]'。谢谢(如果我在d.Revisions中添加'from r'就没有分组,我又回到了原来的位置)。 –
Ricky
我得到它的工作,但我不认为它现在是有效的,现在我从同一个表中选择两个字段(我可能需要更多,因此连接)。我更新了我的问题,请参阅我使用的代码。再次感谢! – Ricky
请参阅我的编辑。 –