Question

En utilisant la syntaxe d'extension, je suis en train de créer une gauche rejoindre LINQ sur deux listes que j'ai. Ce qui suit est de l'aide de Microsoft, mais je l'ai modifié pour montrer que la liste des animaux n'a pas d'éléments. Ce que je veux finir avec une liste de 0 éléments. Je suppose que cela est parce qu'un intérieur jointure est en cours. Ce que je veux retrouver avec une liste de 3 éléments (les 3 objets de personne) avec des données nulles remplies pour les éléments manquants. à-dire une gauche d'inscription. 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<Person> people = new List<Person> { magnus, terry, charlotte };
//List<Pet> pets = new List<Pet> { barley, boots, whiskers, daisy };
List<Pet> pets = new List<Pet>();

// 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();
Était-ce utile?

La solution

Je pense que si vous voulez utiliser des méthodes d'extension, vous devez utiliser le 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 ça vous voulez que vous voulez donner dans le cas où vous avez 1 à plusieurs.

Je pense qu'il est un peu plus facile avec la syntaxe de requête LINQ

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

Autres conseils

Vous devez obtenir les objets réunis en un ensemble, puis appliquez DefaultIfEmpty comme JPunyon dit:

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<Person> people = new List<Person> { magnus, terry, charlotte };
List<Pet> pets = new List<Pet>{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(
        String.Format("{0,-25} has {1}", item.OwnerName, item.Name ) );
}

Sorties:

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

Je le message d'erreur suivant lorsqu'ils sont confrontés à ce même problème:

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

Résolu quand j'utilisé le même nom de la propriété, il a travaillé.

(...)

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 blog qui vient d'être publié par Fabrice (auteur de LINQ en action) qui couvre la matière dans la question que je posais. Je mets ici pour référence que les lecteurs de la question trouveront cela utile.

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

gauche se joint à LINQ sont possibles avec le procédé DefaultIfEmpty (). Je n'ai pas la syntaxe exacte pour votre cas si ...

En fait, je pense que si vous venez de changer les animaux de compagnie à pets.DefaultIfEmpty () dans la requête, il pourrait fonctionner ...

EDIT: Je ne devrais pas répondre à des choses quand sa fin ...

Si vous avez fait une base de données, c'est la façon la 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();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top