我想這個很簡單的一塊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
請參閱我的編輯。 –