使用 EF Core 从数据库中进行复杂选择,无需具体化查询

问题描述 投票:0回答:1

看来我需要EF大师的帮助。因此,我的项目中有带有 EF Core 的 Postgres DB。有一个表RequestDbModel,它可能包含许多具有相同Id和不同ts的行。我需要从此表中选择请求集合,其中项目是具有相同 Id 的行,并且还必须从按 ts 排序的这些项目中填充一些额外的字段。我可以做到这一点,但前提是我要具体化查询。我相信这可以在不实现的情况下完成,但我不知道如何实现,我将不胜感激任何帮助

  • Request.Status - 项目中最新(最新)项目的状态
  • Request.CreatedTime - Items 中第一个(最旧的)项目的 ts
  • Request.AppliedTime - 状态 ==“已批准”的项目中最早的项目 ts
  • Request.CreatorId - 第一个(最旧的)项目的 UserId 物品
  • Request.ApproverId - 项目中最旧项目的用户 ID 状态 ==“已批准”或 null
  • Request.Comment - 给最老的人评论 项目中的项目
// 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;        
}
c# postgresql entity-framework-core
1个回答
0
投票

以下代码可能会有所帮助,但无法测试它:

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
});
© www.soinside.com 2019 - 2024. All rights reserved.