Linq-запрос с подзапросом в виде значений, разделенных запятыми - PullRequest
5 голосов
/ 19 мая 2010

В моем приложении в компании может быть много сотрудников, и у каждого сотрудника может быть несколько адресов электронной почты.

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

Компания -> CompanyEmployeeXref -> Сотрудник -> EmployeeAddressXref -> Электронная почта

Я использую Entity Framework и хочу создать запрос LINQ, который возвращает название компании и разделенный запятыми список адресов электронной почты ее сотрудника. Вот запрос, который я пытаюсь выполнить:

<code>
from c in Company
join ex in CompanyEmployeeXref on c.Id equals ex.CompanyId
join e in Employee on ex.EmployeeId equals e.Id
join ax in EmployeeAddressXref on e.Id equals ax.EmployeeId
join a in Address on ax.AddressId equals a.Id
select new {
              c.Name,
              a.Email.Aggregate(x=>x + ",")
           }
</code>

Desired Output:

"Company1", "a@company1.com,b@company1.com,c@company1.com"

"Company2", "a@company2.com,b@company2.com,c@company2.com"

...

Я знаю, что этот код неправильный, я думаю, что мне не хватает группы, но это иллюстрирует суть. Я не уверен в синтаксисе. Это вообще возможно? Спасибо за любую помощь.

Ответы [ 2 ]

7 голосов
/ 19 мая 2010

Вот теперь я решил проблему:


from c in Company
join ex in CompanyEmployeeXref on c.Id equals ex.CompanyId
join e in Employee on ex.EmployeeId equals e.Id
join ax in EmployeeAddressXref on e.Id equals ax.EmployeeId
join a in Address on ax.AddressId equals a.Id
group a.Email by new {c.Name} into g
select new {
                Company=g.Key.Name,
                Email=g.Select(e=>e).Distinct()
            }
).ToList()
.Select(l=> 
           new {
                    l.Name,
                    Email=string.Join(",", l.Email.ToArray())
                }
        )


5 голосов
/ 19 мая 2010

На самом деле это довольно сложно сделать в чистом Linq to SQL (или Entity Framework, какой бы вы ни использовали), потому что сам SQL Server не имеет оператора агрегирования, который может создать список с разделителями-запятыми, поэтому способ превратить весь этот оператор в один запрос. Я мог бы дать вам ответ Linq to SQL «с одним утверждением», но на самом деле он не даст вам очень хорошую производительность, и я не уверен, будет ли он вообще работать в EF.

Это уродливее, но все же лучше, если вы просто выполните обычное объединение, материализуете результаты, а затем выполните свою конкатенацию, используя Linq to Objects:

var rows =
    (from c in Company
     join ex in CompanyEmployeeXref on c.Id equals ex.CompanyId
     join e in Employee on ex.EmployeeId equals e.Id
     join ax in EmployeeAddressXref on e.Id equals ax.EmployeeId
     join a in Address on ax.AddressId equals a.Id
     select new 
     {
         c.Name,
         a.Email
     }).AsEnumerable();

var emails =
    from r in rows
    group r by r.Name into g
    select new
    {
        Name = g.Key,
        Emails = g.Aggregate((x, y) => x + "," + y)
    };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...