You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LINQ多对多左连接后按Complaint分组及用户归集实现方法

分组Complaint并关联分配的ApplicationUser

1. 先明确实体与ViewModel结构

假设你的实体及ViewModel简化结构如下:

public class Complaint
{
    public int Id { get; set; }
    public string Title { get; set; }
    // 其他业务属性
}

public class ApplicationUser
{
    public string Id { get; set; }
    public string UserName { get; set; }
    // 其他用户属性
}

public class AsignComplaintToUsers
{
    public int ComplaintId { get; set; }
    public string UserId { get; set; }
    public Complaint Complaint { get; set; }
    public ApplicationUser User { get; set; }
}

// 用于展示的ViewModel
public class ComplaintViewModel
{
    public int ComplaintId { get; set; }
    public string ComplaintTitle { get; set; }
    public List<ApplicationUser> AssignedUsers { get; set; } = new List<ApplicationUser>();
    // 其他需要展示的属性
}

2. 分组查询与ViewModel赋值

方式一:基于已有左连接数据分组

如果已经通过左连接获取了包含Complaint、关联表、用户的基础集合,可以直接在内存中分组转换:

// 假设这是你已获取的左连接基础数据
var leftJoinData = _context.Complaints
    .GroupJoin(_context.AsignComplaintToUsers,
        c => c.Id,
        ac => ac.ComplaintId,
        (c, acs) => new { Complaint = c, Assignments = acs.DefaultIfEmpty() })
    .SelectMany(
        x => x.Assignments,
        (x, ac) => new { x.Complaint, ac, User = ac != null ? ac.User : null })
    .ToList();

// 分组并转换为ViewModel
var complaintViewModels = leftJoinData
    .GroupBy(item => item.Complaint.Id)
    .Select(group => new ComplaintViewModel
    {
        ComplaintId = group.Key,
        ComplaintTitle = group.First().Complaint.Title,
        AssignedUsers = group.Where(g => g.User != null).Select(g => g.User).ToList()
    })
    .ToList();

方式二:直接在EF Core查询中完成分组(更高效)

如果还未执行左连接,建议直接在数据库层面完成分组关联,减少内存数据处理压力:

var complaintViewModels = _context.Complaints
    .Select(c => new ComplaintViewModel
    {
        ComplaintId = c.Id,
        ComplaintTitle = c.Title,
        AssignedUsers = _context.AsignComplaintToUsers
            .Where(ac => ac.ComplaintId == c.Id)
            .Select(ac => ac.User)
            .ToList()
    })
    .ToList();

3. 手动遍历分组结果赋值

如果需要逐行处理分组数据而不是直接用Select转换:

var groupedData = leftJoinData.GroupBy(item => item.Complaint.Id);
var complaintViewModels = new List<ComplaintViewModel>();

foreach (var group in groupedData)
{
    var targetComplaint = group.First().Complaint;
    var vm = new ComplaintViewModel
    {
        ComplaintId = group.Key,
        ComplaintTitle = targetComplaint.Title
    };

    // 遍历组内用户,添加到ViewModel集合
    foreach (var item in group)
    {
        if (item.User != null)
        {
            vm.AssignedUsers.Add(item.User);
        }
    }

    complaintViewModels.Add(vm);
}

关键注意点

  • 如果是左连接查询,必须处理User为null的情况,避免空引用异常
  • 优先选择在EF Core查询中完成分组关联,数据量较大时性能优势明显
  • 若已配置实体导航属性(比如Complaint下的AssignedLinks导航到AsignComplaintToUsers),可以进一步简化查询:
    // 前提:Complaint实体已配置导航属性 public ICollection<AsignComplaintToUsers> AssignedLinks { get; set; }
    var viewModel = _context.Complaints
        .Include(c => c.AssignedLinks)
        .ThenInclude(ac => ac.User)
        .Select(c => new ComplaintViewModel
        {
            ComplaintId = c.Id,
            ComplaintTitle = c.Title,
            AssignedUsers = c.AssignedLinks.Select(ac => ac.User).ToList()
        })
        .ToList();
    

内容的提问来源于stack exchange,提问作者Fawad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 22:45:32