web-dev-qa-db-fra.com

Comment faire une jointure dans linq to SQL avec la syntaxe de méthode?

J'ai vu beaucoup d'exemples dans LINQ to SQL exemples sur la façon de faire une jointure dans la syntaxe de requête, mais je me demande comment 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 donner un autre exemple simple?

186
chobo2
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 constater, en ce qui concerne les jointures, la syntaxe de requête est généralement beaucoup plus lisible que la syntaxe lambda.

268
Justin Niessner

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 compliqué à cause de 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 });

La z ici est l'identifiant transparent - mais comme il est transparent, vous ne pouvez pas le voir dans la requête d'origine :)

124
Jon Skeet

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, un objet 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;

}    

Portez une attention particulière à l'objet intermédiaire créé dans les clauses Where et Select.

Notez que nous recherchons également ici tous les objets joints ayant une propriété1 correspondant à l'un de ceux de la liste d'entrée.

Je sais que cela est un peu plus complexe que ce que le demandeur d'origine cherchait, mais j'espère que cela aidera quelqu'un.

5
John Meyer