2011-06-06 20 views
35

Al escribir consultas LINQ en C#, sé que puedo realizar una unión utilizando la palabra clave join. Pero, ¿qué hace lo siguiente?LINQ Unirse con Multiple From Clauses

from c in Companies 
from e in c.Employees 
select e; 

Un libro LINQ tengo dicen que es un tipo de unión, pero no se unen a un adecuado (que utiliza la palabra clave join). ¿Entonces exactamente qué tipo de unión es?

+1

Linq-to-Objects, -Sql, -Entidades? En -Objects, eso no es una unión, sino una operación 'SelectMany'. En los demás, se podría traducir a la izquierda o a la parte interna según los datos. –

+0

@Anthony: No he usado tanto LINQ. Entonces, mi pregunta era solo general y no se limitaba a ningún proveedor específico. Sin embargo, en última instancia, probablemente termine con LINQ to Entities. –

Respuesta

39

Múltiples declaraciones "de" se consideran sentencias de linq compuestas. Son como declaraciones foreach anidadas. La página de MSDN que enumera una gran ejemplo here

var scoreQuery = from student in students 
         from score in student.Scores 
          where score > 90 
          select new { Last = student.LastName, score }; 

esta declaración podría ser reescrita como:

SomeDupCollection<string, decimal> nameScore = new SomeDupCollection<string, float>(); 
foreach(Student curStudent in students) 
{ 
    foreach(Score curScore in curStudent.scores) 
    { 
     if (curScore > 90) 
     { 
     nameScore.Add(curStudent.LastName, curScore); 
     } 
    } 
} 
24

Esto se traducirá a una llamada SelectMany(). Es esencialmente una combinación cruzada.

Jon Skeet habla de ello en su blog, como parte de Edulinq series. (Desplácese hacia abajo a Cláusulas secundarias "de".)

-1

Todo el primer conjunto de objetos se unirá con todo el segundo conjunto de objetos. Por ejemplo, pasará la siguiente prueba ...

[TestMethod()] 
    public void TestJoin() 
    { 
     var list1 = new List<Object1>(); 
     var list2 = new List<Object2>(); 

     list1.Add(new Object1 { Prop1 = 1, Prop2 = "2" }); 
     list1.Add(new Object1 { Prop1 = 4, Prop2 = "2av" }); 
     list1.Add(new Object1 { Prop1 = 5, Prop2 = "2gks" }); 

     list2.Add(new Object2 { Prop1 = 3, Prop2 = "wq" }); 
     list2.Add(new Object2 { Prop1 = 9, Prop2 = "sdf" }); 

     var list = (from l1 in list1 
        from l2 in list2 
        select l1).ToList(); 

     Assert.AreEqual(6, list.Count); 

    } 
+1

Este no es el mismo escenario que el código en cuestión. Está demostrando un producto cartesiano, eso no es lo que es. –

16

el código que ha enumerado:

from c in company 
from e in c.Employees 
select e; 

... producirá una lista de cada empleado para cada compañía en la variable company. Si un empleado trabaja para dos compañías, se incluirán en la lista dos veces.

La única "combinación" que puede aparecer aquí es cuando dices c.Employees. En un proveedor respaldado por SQL, esto se traduciría en una combinación interna de la tabla Company en la tabla Employee.

Sin embargo, el doble from constructo se utiliza a menudo para llevar a cabo "une" manualmente, así:

from c in companies 
from e in employees 
where c.CompanyId == e.CompanyId 
select e; 

Esto tendría un efecto similar como el código que envió, con posibles diferencias sutiles en función de lo la variable employees contiene. Esto también sería equivalente a la siguiente join:

from c in companies 
join e in employees 
    on c.CompanyId equals e.CompanyId 
select e; 

Si quieres un producto cartesiano, sin embargo, sólo podría eliminar la cláusula where. (Para que sea digno de cualquier cosa, lo que probablemente quiere cambiar el select poco, demasiado, sin embargo.)

from c in companies 
from e in employees 
select new {c, e}; 

Esta última consulta que daría a cada posible combinación de empresa y los empleados.