[英]C# LINQ to Entities One-To-Many relationship: Problem displaying last log entry data
我有一個帶有兩個表的Web應用程序來跟蹤用戶份額。 股份必須經過批准,才能進行一系列狀態更改。 每個狀態更改都記錄在日志中並加蓋時間戳。 當前狀態始終是該特定共享的日志中的最后一個條目。
以下是實體(簡潔):
共享:ShareID用戶名
ShareLogs:LogID ShareID創建日期狀態
我正在嘗試根據上一個日志條目獲取具有當前狀態的共享列表。 這是返回正確結果的SQL查詢,但我想使用LINQ進行此操作。
SELECT s.ShareID, s.UserName, sl.Code, sl.CreatedDate
FROM Shares s
INNER JOIN
(
SELECT s.ShareID, s.Code, s.CreatedDate
FROM ShareLogs sl
INNER JOIN (SELECT ShareID, MAX(CreatedDate) logDate FROM ShareLogs GROUP BY ShareID) sl2
ON sl.ShareID = sl2.ShareID AND sl.CreatedDate = sl2.logDate) psl1
ON s.ShareID = sl1.ShareID
ORDER BY s.ShareID
我寫了一個看起來不錯的LINQ查詢,但是我覺得應該有更好的方法,因為這個查詢看起來很糟糕。
var query = from list in
(from s in context.Shares
join sl in context.ShareLogs on s.ShareID equals sl.ShareID
where sl.CreatedDate == s.ShareLogs.Max(e => e.CreatedDate)
select new
{
share = s
status = sl.Code,
processDate = sl.CreatedDate
}).Where(e => e.status == 2 || e.status == 3)
select list;
您可以嘗試進行聯接,然后對除ShareID以外的所有行進行分組,然后僅獲取日期最大的共享。 例如:
var shareList = context.Shares;
var shareLogList = context.ShareLogs;
var join = shareList.Join(shareLogList, o=>o.ShareID, i=>i.ShareID, s=>new{o.ShareID, o.UserName,i.LogID, i.CreatedDate, i.Status});
var query = join.GroupBy(g=>new{g.ShareID,g.UserName}, (key,lines)=>new{key.ShareID, Status = lines.Max(m=>m.CreatedDate).Status});
那應該做! 如果願意,可以將其合並為一個語句,為了清楚起見,我將它們分開。
var query = (from s in context.Shares
let latestOrder = s.ShareLogs
.OrderByDescending(sl => sl.CreatedDate)
.First()
select new
{
share = s,
status = latestOrder.Code,
processDate = latestOrder.CreatedDate
}).Where(sl => sl.status == 2 || sl.status ==3);
讓我知道您是否認為這是一種改進。
編輯:我不是100%知道您需要在哪里過濾器,所以我離開了它。 我認為Let語句中可能實際上需要它。 或者我們可以將其移至Comprehension語法中以使其更加一致。
我更喜歡方法語法,所以這是我的答案。 請注意,我也在進行分組依據,而不是聯接。
context.ShareLogs.GroupBy(log => log.ShareID)
.Select(g => g.Logs.Single(log =>
log.CreatedDate == g.Logs.Max(g => g.CreatedDate)))
.Select(l => new { Share = l.Share, Status = l.Code, Date = l.CreatedDate });
您應該能夠對ShareLogs
進行分組,以確定正確的ShareLog對象(其中包含Code,Date和ShareID),然后使用導航屬性log.Share
檢索Share。
據我所知,不需要聯接,因為LINQ通常通過導航屬性將其隱藏起來。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.