LINQ Inner-Join vs Left-Join

Utilisation de la syntaxe d’extension J’essaie de créer une jointure à gauche en utilisant LINQ sur deux listes que j’ai. Ce qui suit provient de l’aide de Microsoft, mais je l’ai modifié pour montrer que la liste des animaux de compagnie ne contient aucun élément. Ce que je me retrouve avec une liste de 0 éléments. Je suppose que c’est parce qu’une jointure interne a lieu. Ce que je veux finir avec une liste de 3 éléments (les 3 objects Person) avec des données nulles pour les éléments manquants. c’est-à-dire une jointure à gauche. Est-ce possible?

Person magnus = new Person { Name = "Hedlund, Magnus" }; Person terry = new Person { Name = "Adams, Terry" }; Person charlotte = new Person { Name = "Weiss, Charlotte" }; //Pet barley = new Pet { Name = "Barley", Owner = terry }; //Pet boots = new Pet { Name = "Boots", Owner = terry }; //Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte }; //Pet daisy = new Pet { Name = "Daisy", Owner = magnus }; List people = new List { magnus, terry, charlotte }; //List pets = new List { barley, boots, whiskers, daisy }; List pets = new List(); // Create a list of Person-Pet pairs where // each element is an anonymous type that contains a // Pet's name and the name of the Person that owns the Pet. var query = people.Join(pets, person => person, pet => pet.Owner, (person, pet) => new { OwnerName = person.Name, Pet = pet.Name }).ToList(); 

Je pense que si vous voulez utiliser des méthodes d’extension, vous devez utiliser GroupJoin

 var query = people.GroupJoin(pets, person => person, pet => pet.Owner, (person, petCollection) => new { OwnerName = person.Name, Pet = PetCollection.Select( p => p.Name ) .DefaultIfEmpty() } ).ToList(); 

Vous devrez peut-être jouer avec l’expression de sélection. Je ne suis pas sûr que cela vous donnerait envie de vouloir dans le cas où vous avez une relation un-à-plusieurs.

Je pense que c’est un peu plus facile avec la syntaxe LINQ Query

 var query = (from person in context.People join pet in context.Pets on person equals pet.Owner into tempPets from pets in tempPets.DefaultIfEmpty() select new { OwnerName = person.Name, Pet = pets.Name }) .ToList(); 

Vous devez placer les objects joints dans un ensemble, puis appliquer DefaultIfEmpty car JPunyon a déclaré:

 Person magnus = new Person { Name = "Hedlund, Magnus" }; Person terry = new Person { Name = "Adams, Terry" }; Person charlotte = new Person { Name = "Weiss, Charlotte" }; Pet barley = new Pet { Name = "Barley", Owner = terry }; List people = new List { magnus, terry, charlotte }; List pets = new List{barley}; var results = from person in people join pet in pets on person.Name equals pet.Owner.Name into ownedPets from ownedPet in ownedPets.DefaultIfEmpty(new Pet()) orderby person.Name select new { OwnerName = person.Name, ownedPet.Name }; foreach (var item in results) { Console.WriteLine( Ssortingng.Format("{0,-25} has {1}", item.OwnerName, item.Name ) ); } 

Les sorties:

 Adams, Terry has Barley Hedlund, Magnus has Weiss, Charlotte has 

Je le message d’erreur suivant lorsque confronté à ce même problème:

Le type de l’une des expressions de la clause de jointure est incorrect. L’inférence de type a échoué dans l’appel à ‘GroupJoin’.

Résolu lorsque j’ai utilisé le même nom de propriété, cela a fonctionné.

(…)

 join enderecoST in db.PessoaEnderecos on new { CD_PESSOA = nf.CD_PESSOA_ST, CD_ENDERECO_PESSOA = nf.CD_ENDERECO_PESSOA_ST } equals new { enderecoST.CD_PESSOA, enderecoST.CD_ENDERECO_PESSOA } into eST 

(…)

Voici un bon article de blog que Fabrice (auteur de LINQ in Action) vient de publier et qui couvre le contenu de la question que j’ai posée. Je le mets ici pour référence car les lecteurs de la question trouveront cela utile.

Conversion de requêtes LINQ de la syntaxe de requête en syntaxe méthode / opérateur

Les jointures à gauche dans LINQ sont possibles avec la méthode DefaultIfEmpty (). Je n’ai cependant pas la syntaxe exacte pour votre cas …

En fait, je pense que si vous modifiez simplement pets en pets.DefaultIfEmpty () dans la requête, cela pourrait fonctionner …

EDIT: Je ne devrais vraiment pas répondre aux choses quand il est tard …

Si vous avez réellement une firebase database, c’est le moyen le plus simple:

 var lsPetOwners = ( from person in context.People from pets in context.Pets .Where(mypet => mypet.Owner == person.ID) .DefaultIfEmpty() select new { OwnerName = person.Name, Pet = pets.Name } ).ToList();