2010-05-18 23 views
5

En mi aplicación, una empresa puede tener muchos empleados y cada empleado puede tener varias direcciones de correo electrónico.Consulta de Linq con subconsulta como valores separados por comas

El esquema de base de datos relaciona las tablas como esta:

empresa -> CompanyEmployeeXref -> Empleado -> EmployeeAddressXref -> Correo electrónico

estoy usando Entity Framework y quiero crear una consulta LINQ que devuelve el nombre de la compañía y una lista separada por comas de sus direcciones de correo electrónico. Ésta es la consulta que intento:

 

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", "[email protected],[email protected],[email protected]" 

"Company2", "[email protected],[email protected],[email protected]" 

... 

Sé que este código es incorrecto, creo que me falta por un grupo, pero ilustra el punto. No estoy seguro de la sintaxis. ¿Esto es posible? Gracias por cualquier ayuda.

+0

Tengo un código que hace esto pero ejecutaría un nuevo lote para cada compañía en su caso. Lo publicaré mañana a menos que alguien tenga algo mejor que sugerir. –

Respuesta

7

He aquí ahora he resuelto el problema:

 

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

 
+0

¿Has rastreado esto para ver qué SQL está usando? –

+0

funcionó como un encanto. Gracias –

5

En realidad, es bastante difícil hacer esto en Linq puro a SQL (o Entity Framework, cualquiera que esté usando) porque SQL Server no tiene ningún operador agregado que pueda producir una lista delimitada por comas, por lo que tiene no hay forma de transformar esta declaración completa en una sola consulta. Podría darte una respuesta de Linq a SQL de "declaración única", pero en realidad no te dará muy buen rendimiento, y no estoy seguro de si funcionaría en absoluto en EF.

Es más feo pero aún mejor si simplemente se inscribe en un regular, materializar los resultados, a continuación, hacer su concatenación utilizando LINQ a Objetos:

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