Domanda

Utilizzando la sintassi estensione Sto cercando di creare un sinistra-join utilizzando LINQ su due liste che ho. Quanto segue è da l'aiuto di Microsoft, ma ho modificato per mostrare che l'elenco animali non ha elementi. Quello che sto per finire con una lista di elementi 0. Presumo che questo è perché un inner-join è in corso. Quello che voglio finire con un elenco di 3 elementi (i 3 oggetti persona) con dati nulli compilati per gli elementi mancanti. vale a dire una sinistra-join. È possibile?

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();
È stato utile?

Soluzione

Credo che se si desidera utilizzare metodi di estensione è necessario utilizzare il 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();

Potrebbe essere necessario giocare con l'espressione di selezione. Io non sono sicuro che darebbe si vuole si vuole nel caso in cui si ha un rapporto 1-a-molti.

Credo che sia un po 'più facile con la sintassi 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();

Altri suggerimenti

È necessario per ottenere gli oggetti uniti in un set e quindi applicare DefaultIfEmpty come diceva JPunyon:

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

Uscite:

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

I il seguente messaggio di errore quando ha affrontato lo stesso problema:

Il tipo di una delle espressioni nella clausola join non è corretto. Inferenza di tipo fallito nella chiamata a 'GroupJoin'.

risolto quando ho usato lo stesso nome della proprietà, ha funzionato.

(...)

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

(...)

Ecco un buon post sul blog che è stato appena pubblicato da Fabrice (autore di LINQ in Action), che copre il materiale nella domanda che ho chiesto. Sto mettendo qui per riferimento come i lettori della questione troveranno questo utile.

Conversione query LINQ dalla sintassi di query al metodo / operatore di sintassi

A sinistra si unisce in LINQ sono possibili con il metodo DefaultIfEmpty (). Non ho la sintassi esatta per il vostro caso però ...

In realtà penso che se basta cambiare gli animali domestici a pets.DefaultIfEmpty () nella query che potrebbe funzionare ...

EDIT: Non dovrei rispondere a cose quando la sua fine ...

Se effettivamente dispone di un database, questo è il modo più semplice-:

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();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top