看来我需要EF大师的帮助。因此,我的项目中有带有 EF Core 的 Postgres DB。有一个表RequestDbModel,它可能包含许多具有相同Id和不同ts的行。我需要从此表中选择请求集合,其中项目是具有相同 Id 的行,并且还必须从按 ts 排序的这些项目中填充一些额外的字段。我可以做到这一点,但前提是我要具体化查询。我相信这可以在不实现的情况下完成,但我不知道如何实现,我将不胜感激任何帮助
// builder.HasKey(p => new { p.Id, p.Timestamp })
// .HasName("requests_pkey");
public class RequestDbModel
{
public long Id { get; init; }
public required string Status { get; set; }
public required DateTime Timestamp { get; init; }
public required Guid UserId { get; init; }
public string? Comment { get; init; }
}
public sealed class Request
{
public required long Id { get; init; }
public required string Status { get; init; }
public DateTime CreatedTime { get; init; }
public DateTime? AppliedTime { get; init; }
public required Guid CreatorId { get; init; }
public Guid? ApproverId { get; init; }
public string? Comment { get; init; }
public required RequestItemHistory[] Items { get; init; }
}
public sealed class RequestItemHistory
{
public required string Status { get; init; }
public required DateTime Timestamp { get; init; }
public required Guid UserId { get; init; }
public string? Comment { get; init; }
}
public IQueryable<Request> GetRequests()
{
var groups = context.Requests.AsNoTracking()
.GroupBy(r => r.Id)
.Select(g => new
{
Id = g.Key,
Items = g.OrderBy(r => r.Timestamp).Select(r => new RequestItemHistory
{
Status = r.Status,
Timestamp = r.Timestamp,
UserId = r.UserId,
Comment = r.Comment,
})//.ToList()
});
var result = groups
.ToList()
.Select(x => new Request
{
Id = x.Id,
Status = x.Items.Last().Status,
CreatedTime = x.Items.First().Timestamp,
AppliedTime = x.Items.Where(i => i.Status == "Approved").OrderByDescending(i => i.Timestamp).Select(i => (DateTime?)i.Timestamp).FirstOrDefault(),
CreatorId = x.Items.First().User,
ApproverId = x.Items.Where(i => i.Status == "Approved").OrderByDescending(i => i.Timestamp).Select(i => i.User).FirstOrDefault(),
Comment = x.Items.Last().Comment,
Items = x.Items.ToArray()
}).AsQueryable();
return result;
}
以下代码可能会有所帮助,但无法测试它:
var groupedQueryable = dbSet.GroupBy(p => p.Id)
.Select(p => new
{
Id = p.Key,
Items = p.SelectMany(c => c.Items),
FirstHistory = p.SelectMany(a => a.Items).OrderBy(c => c.Timestamp).First(),
LastHistory = p.SelectMany(c => c.Items).OrderByDescending(c => c.Timestamp).First(),
FirstApprovedHistory = p.SelectMany(c => c.Items).Where(c => c.Status == "Approved")
.OrderBy(c => c.Timestamp).First()
});
return groupedQueryable.Select(c => new Request
{
Status = c.LastHistory.Status,
CreatedTime = c.FirstHistory.Timestamp,
AppliedTime = c.FirstApprovedHistory.Timestamp,
CreatorId = c.FirstHistory.UserId,
ApproverId = c.FirstApprovedHistory.UserId,
Comment = c.LastHistory.Comment,
Items = c.Items
});