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

多对多关联数据最优获取方案:如何关联User等多角色类实现列表需求

解决方案

以下三种优化方案可根据你的技术栈和可修改范围选择:

方案1:给User类补充导航属性(最优,符合ORM设计规范)

直接在User类中补充关联对象的导航属性,结合业务规则封装身份信息快捷访问属性:

class User
{
    // 原有属性省略
    public Intern? InternInfo { get; set; }
    public Employee? EmployeeInfo { get; set; }
    public ICollection<Plumber>? PlumberPosts { get; set; }
    public ICollection<Technician>? TechnicianPosts { get; set; }

    // 快捷属性,直接返回用户身份类型和对应编号
    public string IdentityType => InternInfo != null ? "Intern" : "Employee";
    public string IdentityNumber => InternInfo?.InternNumber ?? EmployeeInfo?.EmployeeNumber ?? string.Empty;
}

之后生成目标列表时可直接访问导航属性,无需额外查询:

// 生成Plumber列表
var plumberList = plumbers.Select(p => new 
{
    p.Id,
    p.PlumberNumber,
    p.UserId,
    IdentityType = p.U.IdentityType,
    IdentityNumber = p.U.IdentityNumber
}).ToList();

// Technician列表写法完全一致
var technicianList = technicians.Select(t => new 
{
    t.Id,
    t.TechnicianNumber,
    t.UserId,
    IdentityType = t.U.IdentityType,
    IdentityNumber = t.U.IdentityNumber
}).ToList();

方案2:预构建身份字典(无法修改实体类时首选)

如果不能调整实体类结构,可一次性加载所有用户的身份信息生成字典,将遍历过程中的查找复杂度从O(n)降到O(1),避免重复Linq查询:

// 仅查询一次,构建UserId到身份信息的映射字典
var userIdentityDict = interns
    .Select(i => new { i.UserId, Type = "Intern", Number = i.InternNumber })
    .Concat(employees.Select(e => new { e.UserId, Type = "Employee", Number = e.EmployeeNumber }))
    .ToDictionary(x => x.UserId);

// 生成Plumber列表,直接走字典快速查询
var plumberList = plumbers.Select(p => new
{
    p.Id,
    p.PlumberNumber,
    p.UserId,
    IdentityType = userIdentityDict[p.UserId].Type,
    IdentityNumber = userIdentityDict[p.UserId].Number
}).ToList();

方案3:EF Core场景下数据库层面直接投影

如果是用EF Core从数据库查询数据,直接在查询阶段做关联投影,由数据库引擎优化关联逻辑,无需加载全量数据到内存:

var plumberList = await dbContext.Plumbers
    .Select(p => new
    {
        p.Id,
        p.PlumberNumber,
        p.UserId,
        IdentityType = dbContext.Interns.Any(i => i.UserId == p.UserId) ? "Intern" : "Employee",
        IdentityNumber = dbContext.Interns.Where(i => i.UserId == p.UserId).Select(i => i.InternNumber).FirstOrDefault()
            ?? dbContext.Employees.Where(e => e.UserId == p.UserId).Select(e => e.EmployeeNumber).FirstOrDefault()
    })
    .ToListAsync();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 18:48:03