LINQ Inner-Join vs Left-Join

Usando la syntax de extensión, bash crear una combinación a la izquierda usando LINQ en dos listas que tengo. Lo siguiente es de la ayuda de Microsoft pero lo he modificado para mostrar que la lista de mascotas no tiene elementos. Lo que estoy terminando es una lista de 0 elementos. Supongo que esto se debe a que se está produciendo una unión interna. Con lo que quiero terminar es con una lista de 3 elementos (los objetos de 3 personas) con datos nulos completados para los elementos faltantes. es decir, un Left-Join. es posible?

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

Creo que si quieres usar métodos de extensión necesitas usar 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(); 

Puede que tenga que jugar con la expresión de selección. No estoy seguro de que pueda darle el deseo que desea en el caso en que tenga una relación de uno a varios.

Creo que es un poco más fácil con la syntax 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(); 

Debes obtener los objetos unidos en un conjunto y luego aplicar DefaultIfEmpty como JPunyon dijo:

 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( String.Format("{0,-25} has {1}", item.OwnerName, item.Name ) ); } 

Productos:

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

I el siguiente mensaje de error cuando enfrenta este mismo problema:

El tipo de una de las expresiones en la cláusula join es incorrecto. La inferencia de tipo falló en la llamada a ‘GroupJoin’.

Resuelto cuando utilicé el mismo nombre de propiedad, funcionó.

(…)

 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 

(…)

Aquí hay una buena publicación de blog que acaba de publicar Fabrice (autor de LINQ en acción) que cubre el material en la pregunta que hice. Lo estoy poniendo aquí como referencia ya que los lectores de la pregunta encontrarán esto útil.

Conversión de consultas LINQ de syntax de consulta a syntax de método / operador

Las combinaciones a la izquierda en LINQ son posibles con el método DefaultIfEmpty (). Aunque no tengo la syntax exacta para tu caso …

En realidad, creo que si cambias a las mascotas por mascotas. De lo contrario, si Vacío () en la consulta podría funcionar …

EDITAR: Realmente no debería responder las cosas cuando sea tarde …

Si realmente tiene una base de datos, esta es la forma más 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();