Linq 如何聚合联接?

Linq 如何聚合联接?,linq,linq-to-objects,aggregate,Linq,Linq To Objects,Aggregate,我有三个相关的表格: Employee(EmployeeId, EmployeeName) Skill(SkillId, SkillName) EmployeeSkill(EmployeSkillId, EmployeeId, SkillId) employeeskillid是一个标识 数据库中的行如下所示: John Doe, "Skill-1, Skill2, Skill-3" 员工表: 也就是说,将该员工的技能名称连接到单个字符串中 我尝试了以下方法,但不起作用

我有三个相关的表格:

Employee(EmployeeId, EmployeeName)

Skill(SkillId, SkillName)

EmployeeSkill(EmployeSkillId, EmployeeId, SkillId)
employeeskillid
是一个标识

数据库中的行如下所示:

John Doe, "Skill-1, Skill2, Skill-3"
员工表: 也就是说,将该员工的技能名称连接到单个字符串中

我尝试了以下方法,但不起作用

var query = from emp in Employee.All()
            from es in emp.EmployeeSkills
            join sk in Skill.All() on es.SkillId equals sk.SkillId
            group sk by new {emp.EmployeeName} into g
            select new TestEntity
            {
                Name = g.Key.EmployeeName,
                Skills = g.Aggregate(new StringBuilder(),
                                     (sb, grp_row) => sb.Append(grp_row.SkillName))
                          .ToString()
            };

技能名称的聚合列表返回为空。我如何才能做到这一点?

听起来您可以将加入作为选择的一部分:

var query = from emp in Employee.All()
            select new TestEntity {
                Name = emp.EmployeeName,
                Skills = string.Join(", ", 
                       (from es in emp.EmployeeSkills
                        join sk in Skill.All() on es.SkillId equals sk.SkillId
                        select sk.SkillName)) };
现在,我们将分别为每一个单独地进行连接,这不是非常有效。另一个选项是首先构建从技能ID到技能名称的映射:

var skillMap = Skill.All().ToDictionary(sk => sk.SkillId,
                                        sk => sk.SkillName);
那么主查询就很简单了:

var query = from emp in Employee.All()
            select new TestEntity {
                Name = emp.EmployeeName,
                Skills = string.Join(", ",
                       emp.EmployeeSkills.Select(sk => skillMap[sk.SkillId]))};
最终有很多方法可以剥这只猫的皮-例如,如果你想坚持你原来的方法,那仍然是可行的。我会这样做:

var query = from emp in Employee.All()
            from es in emp.EmployeeSkills
            join sk in Skill.All() on es.SkillId equals sk.SkillId
            group sk.SkillName by emp into g
            select new TestEntity
            {
                Name = g.Key.EmployeeName,
                Skills = string.Join(", ", g)
            };
在这一点上,它与原始查询非常相似,只是使用了
string.Join
而不是
Aggregate
。如果这三种方法的技能列表都是空的,那么我怀疑你的数据有问题。我不清楚为什么您的第一个查询会“成功”,但技能列表是空的

编辑:好的,这里有一个简短但完整的示例:

using System;
using System.Collections.Generic;
using System.Linq;

public class Employee
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }

    public static List<Employee> All { get; set; }

    public IEnumerable<EmployeeSkill> EmployeeSkills
    {
        get 
        { 
            return EmployeeSkill.All
                           .Where(x => x.EmployeeId == EmployeeId);
        }
    }
}

public class Skill
{
    public string SkillName { get; set; }
    public int SkillId { get; set; }

    public static List<Skill> All { get; set; }
}

public class EmployeeSkill
{
    public int SkillId { get; set; }
    public int EmployeeId { get; set; }

    public static List<EmployeeSkill> All { get; set; }
}

class Test
{
    static void Main()
    {
        Skill.All = new List<Skill>
        {
            new Skill { SkillName = "C#", SkillId = 1},
            new Skill { SkillName = "Java", SkillId = 2},
            new Skill { SkillName = "C++", SkillId = 3},
        };

        Employee.All = new List<Employee>
        {
            new Employee { EmployeeName = "Fred", EmployeeId = 1 },
            new Employee { EmployeeName = "Ginger", EmployeeId = 2 },
        };

        EmployeeSkill.All = new List<EmployeeSkill>
        {
            new EmployeeSkill { SkillId = 1, EmployeeId = 1 },
            new EmployeeSkill { SkillId = 2, EmployeeId = 1 },
            new EmployeeSkill { SkillId = 2, EmployeeId = 2 },
            new EmployeeSkill { SkillId = 3, EmployeeId = 2 },
        };

        var query = from emp in Employee.All
            from es in emp.EmployeeSkills
            join sk in Skill.All on es.SkillId equals sk.SkillId
            group sk.SkillName by emp.EmployeeName into g
            select new
            {
                Name = g.Key,
                Skills = string.Join(", ", g)
            };

        foreach (var result in query)
        {
            Console.WriteLine(result);
        }
    }
}

嗨,乔恩。谢谢你这么快回复。这很奇怪,但两个选项都将Skills属性返回为空。我确信这不是数据,因为只使用连接并为每个员工/技能返回一行就行了。知道是什么导致聚合不起作用吗?@silverCORE:听起来很奇怪。。。如果您添加更改以使用“Skills=g.Count().ToString();”之类的内容,您是否获得了正确数量的技能?如果所有的方法都给出了相同的奇怪结果,那听起来确实有数据问题。如果你能给出一个简短但完整的例子,那将非常有帮助。我会尝试自己建立一个。让我粘贴Jon的数据,并尝试g.计数。在上一个示例中,显示“emp.EmployeeName下的group sk.SkillName”的部分显然使尝试使用g.Key.EmployeeName变得不可行。至少我的智能感知没有接收到它。@silverCORE:是的,应该是按emp分组,或者按emp.EmployeeName分组,然后只使用g.Key。我已经编辑了这个查询,还包括了一个简短但完整的示例。我想知道你是否只是没能正确显示结果?我认为这个问题很好。乔恩,你就是那个人。谢谢你抽出时间来帮助我。非常感谢。我已经为你安排好了问题的格式。应该给你一个想法,如何得到你未来的问题你想要它。谢谢杰夫M,我一定会学会怎么做:)
var query = from emp in Employee.All()
            select new TestEntity {
                Name = emp.EmployeeName,
                Skills = string.Join(", ",
                       emp.EmployeeSkills.Select(sk => skillMap[sk.SkillId]))};
var query = from emp in Employee.All()
            from es in emp.EmployeeSkills
            join sk in Skill.All() on es.SkillId equals sk.SkillId
            group sk.SkillName by emp into g
            select new TestEntity
            {
                Name = g.Key.EmployeeName,
                Skills = string.Join(", ", g)
            };
using System;
using System.Collections.Generic;
using System.Linq;

public class Employee
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }

    public static List<Employee> All { get; set; }

    public IEnumerable<EmployeeSkill> EmployeeSkills
    {
        get 
        { 
            return EmployeeSkill.All
                           .Where(x => x.EmployeeId == EmployeeId);
        }
    }
}

public class Skill
{
    public string SkillName { get; set; }
    public int SkillId { get; set; }

    public static List<Skill> All { get; set; }
}

public class EmployeeSkill
{
    public int SkillId { get; set; }
    public int EmployeeId { get; set; }

    public static List<EmployeeSkill> All { get; set; }
}

class Test
{
    static void Main()
    {
        Skill.All = new List<Skill>
        {
            new Skill { SkillName = "C#", SkillId = 1},
            new Skill { SkillName = "Java", SkillId = 2},
            new Skill { SkillName = "C++", SkillId = 3},
        };

        Employee.All = new List<Employee>
        {
            new Employee { EmployeeName = "Fred", EmployeeId = 1 },
            new Employee { EmployeeName = "Ginger", EmployeeId = 2 },
        };

        EmployeeSkill.All = new List<EmployeeSkill>
        {
            new EmployeeSkill { SkillId = 1, EmployeeId = 1 },
            new EmployeeSkill { SkillId = 2, EmployeeId = 1 },
            new EmployeeSkill { SkillId = 2, EmployeeId = 2 },
            new EmployeeSkill { SkillId = 3, EmployeeId = 2 },
        };

        var query = from emp in Employee.All
            from es in emp.EmployeeSkills
            join sk in Skill.All on es.SkillId equals sk.SkillId
            group sk.SkillName by emp.EmployeeName into g
            select new
            {
                Name = g.Key,
                Skills = string.Join(", ", g)
            };

        foreach (var result in query)
        {
            Console.WriteLine(result);
        }
    }
}
{ Name = Fred, Skills = C#, Java }
{ Name = Ginger, Skills = Java, C++ }