Requête Linq avec sous-requête comme valeurs séparées par des virgules

dans ma demande, une entreprise peut avoir plusieurs employés et chaque employé peut avoir plusieurs adresses de courriel.

le schéma de base de données relie les tables comme ceci:

Société - > Société Employéeexref - > Salarié - > Employéadressexref - > Email

j'utilise Entity Framework et je veux créer une requête LINQ qui retourne le nom de la société et une liste de ses adresses email séparées par des virgules. Voici la requête que j'essaie:


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 + ",")
           }


Desired Output:

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

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

...

je sais que ce code est erroné, je pense que je manque un groupe par, mais il illustre le point. Je ne suis pas sûr de la syntaxe. Est-ce même possible? Merci pour toute aide.

5
demandé sur Keith 2010-05-19 01:15:01

2 réponses

Voici maintenant j'ai résolu le problème:


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


7
répondu Keith 2010-05-18 22:29:04

il est en fait assez difficile de faire cela en pure Linq to SQL (ou en Entity Framework, quel que soit celui que vous utilisez) parce que SQL Server lui-même n'a pas d'opérateur agrégat qui peut produire une liste délimitée par une virgule, Donc il n'a aucun moyen de transformer cette déclaration entière en une seule requête. Je pourrais vous donner une réponse "simple-déclaration" Linq à SQL mais en fait, il ne va pas vous donner une très bonne performance, et je ne suis pas sûr que cela fonctionnerait du tout dans EF.

C'est encore plus laid mais encore mieux si vous faites juste une jonction régulière, matérialisez les résultats, puis faites votre concaténation en utilisant Linq aux objets:

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)
    };
5
répondu Aaronaught 2010-05-18 21:31:09