Comment faire une jointure dans linq vers sql avec la syntaxe de la méthode?

193

J'ai vu beaucoup d'exemples dans des exemples LINQ to SQL sur la façon de faire une jointure dans la syntaxe de requête, mais je me demande comment le faire avec la syntaxe de méthode? Par exemple, comment pourrais-je faire ce qui suit

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

avec un .Join()? Quelqu'un peut-il illustrer ou fournir un autre exemple simple?

chobo2
la source

Réponses:

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

Serait équivalent à:

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

Comme vous pouvez le voir, en ce qui concerne les jointures, la syntaxe de requête est généralement beaucoup plus lisible que la syntaxe lambda.

Justin Niessner
la source
129

Justin a correctement montré l'expansion dans le cas où la jointure est juste suivie d'un select. Si vous avez autre chose, cela devient plus délicat en raison des identificateurs transparents - le mécanisme utilisé par le compilateur C # pour propager la portée des deux moitiés de la jointure.

Donc, pour changer légèrement l'exemple 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 }

serait converti en quelque chose comme ceci:

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

Le zici est l'identifiant transparent - mais parce qu'il est transparent, vous ne pouvez pas le voir dans la requête initiale :)

Jon Skeet
la source
5

Pour ajouter aux autres réponses ici, si vous souhaitez créer un nouvel objet d'un troisième type différent avec une clause where (par exemple, une clause qui n'est pas votre objet Entity Framework), vous pouvez le faire:

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;

}    

Faites particulièrement attention à l'objet intermédiaire créé dans les clauses Where et Select.

Notez qu'ici nous recherchons également tous les objets joints qui ont une propriété1 qui correspond à l'un de ceux de la liste d'entrée.

Je sais que c'est un peu plus complexe que ce que le demandeur initial recherchait, mais j'espère que cela aidera quelqu'un.

John Meyer
la source