Как я объединяю объединения? - PullRequest
0 голосов
/ 22 февраля 2011

У меня есть три связанных таблицы:

Employee(EmployeeId, EmployeeName)

Skill(SkillId, SkillName)

EmployeeSkill(EmployeSkillId, EmployeeId, SkillId)

EmployeSkillId - это идентификатор.

Строки в базе данных следующие:

Таблица сотрудников:

EmployeeId | EmployeeNumber | EmployeeName
---------- | -------------- | ------------
        1  |         10015  |  John Doe

Таблица навыков:

SkillId | SkillName
------- | ---------
     1  |  .NET
     2  |  SQL
     3  |  OOD
     4  |  Leadership

Таблица EmployeeSkill:

EmployeeSkillId | EmployeeId | SkillId
--------------- | ---------- | -------
             1  |         1  |      1
             2  |         1  |      2
             3  |         1  |      3
             4  |         1  |      4

Если у меня есть сотрудник с тремя навыками, зарегистрированными в EmployeSkill, я быхотелось бы иметь возможность получить следующий результат:

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()
            };

Сводный список имен умений возвращается пустым.Как я могу это сделать?

1 Ответ

1 голос
/ 22 февраля 2011

Похоже, что вы можете сделать объединение как часть выбора:

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)) };

Теперь мы проведем объединение отдельно для каждого, что не очень эффективно. Другой вариант - сначала построить отображение из идентификатора навыка в название навыка:

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, конечно. Если все эти три подхода вернутся с пустым списком навыков, то я подозреваю, что с вашими данными что-то не так. Мне не очевидно, почему ваш первый запрос будет «успешным», но с пустым списком навыков.

РЕДАКТИРОВАТЬ: Хорошо, вот короткий (-ish), но полный пример его работы:

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++ }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...