LINQ Unión interna vs Izquierda-Ingreso
Pregunta
El uso de la sintaxis de extensión que estoy tratando de crear una izquierda se unen utilizando LINQ en dos listas que tengo. El siguiente es de la ayuda de Microsoft, pero he modificado para mostrar que la lista de mascotas no tiene elementos. Lo que estoy terminando con una lista de elementos 0. Asumo que esto se debe a una Unión interna está teniendo lugar. Lo que quiero es terminar con una lista de 3 elementos (los objetos Persona 3) con datos nulos rellenaron de los elementos que faltan. es decir, una izquierda-Unir. ¿Es esto 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<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();
Solución
Creo que si desea utilizar los métodos de extensión es necesario utilizar la 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();
Es posible que tenga que jugar con la expresión de la selección. No estoy seguro de que daría desea que desear en el caso de que usted tiene una relación de 1 a varios.
Creo que es un poco más fácil con la sintaxis de consultas 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();
Otros consejos
Es necesario para conseguir los objetos unidas en un conjunto y luego aplicar DefaultIfEmpty como dijo 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 ) );
}
Salidas:
Adams, Terry has Barley
Hedlund, Magnus has
Weiss, Charlotte has
el siguiente mensaje de error cuando se enfrentan el mismo problema:
El tipo de una de las expresiones de la cláusula de combinación es incorrecta. La inferencia de tipos falló en la llamada a 'GroupJoin'.
resuelve cuando he usado 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
(...)
He aquí una buena entrada de blog que acaba de ser publicado por Fabrice (autor de LINQ en Acción), que cubre el material en la pregunta que le hice. Me estoy poniendo aquí por referencia como lectores de la cuestión se encuentra este útil.
conversión de consultas LINQ de sintaxis de consulta con el método / operador sintaxis
Izquierda se une en LINQ son posibles con el método DefaultIfEmpty (). No tengo la sintaxis exacta para su caso, sin embargo ...
En realidad creo que si se acaba de cambiar a los animales domésticos pets.DefaultIfEmpty () en la consulta que podría funcionar ...
EDIT: Realmente no debería responder a las cosas cuando es tarde ...
Si usted tiene realmente una base de datos, esta es la manera 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();