¿Cómo hacer una unión en linq a sql con la sintaxis del método?

193

He visto muchos ejemplos en LINQ to SQL ejemplos sobre cómo hacer una unión en la sintaxis de consulta, pero me pregunto cómo hacerlo con la sintaxis del método. Por ejemplo, ¿cómo podría hacer lo siguiente?

var result = from sc in enumerableOfSomeClass
             join soc in enumerableOfSomeOtherClass
             on sc.Property1 equals soc.Property2
             select new { SomeClass = sc, SomeOtherClass = soc }

con un .Join()? ¿Alguien puede ilustrar u ofrecer otro ejemplo simple?

chobo2
fuente

Respuestas:

283
var result = from sc in enumerableOfSomeClass
             join soc in enumerableOfSomeOtherClass
             on sc.Property1 equals soc.Property2
             select new { SomeClass = sc, SomeOtherClass = soc };

Sería equivalente a:

var result = enumerableOfSomeClass
    .Join(enumerableOfSomeOtherClass,
          sc => sc.Property1,
          soc => soc.Property2,
          (sc, soc) => new
                       {
                           SomeClass = sc,
                           SomeOtherClass = soc
                       });

Como puede ver, cuando se trata de combinaciones, la sintaxis de consulta suele ser mucho más legible que la sintaxis lambda.

Justin Niessner
fuente
129

Justin ha mostrado correctamente la expansión en el caso en que la unión solo es seguida por a select. Si tienes algo más, se vuelve más complicado debido a los identificadores transparentes : el mecanismo que utiliza el compilador de C # para propagar el alcance de ambas mitades de la unión.

Entonces, para cambiar un poco el ejemplo de Justin:

var result = from sc in enumerableOfSomeClass
             join soc in enumerableOfSomeOtherClass
             on sc.Property1 equals soc.Property2
             where sc.X + sc.Y == 10
             select new { SomeClass = sc, SomeOtherClass = soc }

se convertiría en algo como esto:

var result = enumerableOfSomeClass
    .Join(enumerableOfSomeOtherClass,
          sc => sc.Property1,
          soc => soc.Property2,
          (sc, soc) => new { sc, soc })
    .Where(z => z.sc.X + z.sc.Y == 10)
    .Select(z => new { SomeClass = z.sc, SomeOtherClass = z.soc });

El zaquí es el identificador transparente - sino porque es transparente, no se puede ver en la consulta original :)

Jon Skeet
fuente
5

Para agregar a las otras respuestas aquí, si desea crear un nuevo objeto de un tercer tipo diferente con una cláusula where (por ejemplo, uno que no sea su objeto Entity Framework), puede hacer esto:

public IEnumerable<ThirdNonEntityClass> demoMethod(IEnumerable<int> property1Values)
{
    using(var entityFrameworkObjectContext = new EntityFrameworkObjectContext )
    {
        var result = entityFrameworkObjectContext.SomeClass
            .Join(entityFrameworkObjectContext.SomeOtherClass,
                sc => sc.property1,
                soc => soc.property2,
                (sc, soc) => new {sc, soc})
            .Where(s => propertyValues.Any(pvals => pvals == es.sc.property1)
            .Select(s => new ThirdNonEntityClass 
            {
                dataValue1 = s.sc.dataValueA,
                dataValue2 = s.soc.dataValueB
            })
            .ToList();
    }

    return result;

}    

Preste especial atención al objeto intermedio que se crea en las cláusulas Where y Select.

Tenga en cuenta que aquí también buscamos cualquier objeto unido que tenga una propiedad1 que coincida con uno de los de la lista de entrada.

Sé que esto es un poco más complejo de lo que estaba buscando el autor de la pregunta original, pero espero que ayude a alguien.

John Meyer
fuente