c# - inner - Cómo realizar la unión entre varias tablas en LINQ lambda
linq consulta dos tablas (4)
Lo que has visto es lo que obtienes, y es exactamente lo que pediste, aquí:
(ppc, c) => new { productproductcategory = ppc, category = c}
Esa es una expresión lambda que devuelve un tipo anónimo con esas dos propiedades.
En sus Productos Categorizados, solo necesita ir a través de esas propiedades:
CategorizedProducts catProducts = query.Select(
m => new {
ProdId = m.productproductcategory.product.Id,
CatId = m.category.CatId,
// other assignments
});
Estoy intentando realizar una combinación entre varias tablas en LINQ. Tengo las siguientes clases:
Product {Id, ProdName, ProdQty}
Category {Id, CatName}
ProductCategory{ProdId, CatId} //association table
Y uso el siguiente código (donde product
, category
y productcategory
son instancias de las clases anteriores):
var query = product.Join(productcategory, p => p.Id, pc => pc.ProdID, (p, pc) => new {product = p, productcategory = pc})
.Join(category, ppc => ppc.productcategory.CatId, c => c.Id, (ppc, c) => new { productproductcategory = ppc, category = c});
Con este código, obtengo un objeto de la siguiente clase:
QueryClass { productproductcategory, category}
Donde producproductcategory es de tipo:
ProductProductCategoryClass {product, productcategory}
No entiendo dónde está la "tabla" unida, esperaba una única clase que contiene todas las propiedades de las clases involucradas.
Mi objetivo es poblar otro objeto con algunas propiedades resultantes de la consulta:
CategorizedProducts catProducts = query.Select(m => new { m.ProdId = ???, m.CatId = ???, //other assignments });
¿Cómo puedo lograr este objetivo?
Para las uniones, prefiero fuertemente la sintaxis de consulta para todos los detalles que están felizmente ocultos (no menos importante son los identificadores transparentes involucrados con las proyecciones intermedias en el camino que son evidentes en el equivalente de sintaxis de punto). Sin embargo, preguntaste sobre Lambdas, que creo que tienes todo lo que necesitas, solo tienes que ponerlo todo junto.
var categorizedProducts = product
.Join(productcategory, p => p.Id, pc => pc.ProdId, (p, pc) => new { p, pc })
.Join(category, ppc => ppc.pc.CatId, c => c.Id, (ppc, c) => new { ppc, c })
.Select(m => new {
ProdId = m.ppc.p.Id, // or m.ppc.pc.ProdId
CatId = m.c.CatId
// other assignments
});
Si es necesario, puede guardar la unión en una variable local y volver a utilizarla más adelante, aunque no tenga otros detalles en contrario, no veo ninguna razón para introducir la variable local.
Además, puede lanzar Select
en la última lambda de la segunda Join
(de nuevo, siempre que no haya otras operaciones que dependan de los resultados de la combinación) que daría:
var categorizedProducts = product
.Join(productcategory, p => p.Id, pc => pc.ProdId, (p, pc) => new { p, pc })
.Join(category, ppc => ppc.pc.CatId, c => c.Id, (ppc, c) => new {
ProdId = ppc.p.Id, // or ppc.pc.ProdId
CatId = c.CatId
// other assignments
});
... y haciendo un último intento de venderle en la sintaxis de la consulta, esto se vería así:
var categorizedProducts =
from p in product
join pc in productcategory on p.Id equals pc.ProdId
join c in category on pc.CatId equals c.Id
select new {
ProdId = p.Id, // or pc.ProdId
CatId = c.CatId
// other assignments
};
Tus manos pueden estar atadas a si la sintaxis de consulta está disponible. Sé que algunas tiendas tienen tales mandatos, a menudo basados en la noción de que la sintaxis de consultas es algo más limitada que la sintaxis de puntos. Hay otras razones, como "¿por qué debería aprender una segunda sintaxis si puedo hacer todo y más en sintaxis de puntos?" Como muestra esta última parte, hay detalles que esconde la sintaxis de consulta que puede hacer que valga la pena abrazar la mejora de la legibilidad que trae: todas esas proyecciones e identificadores intermedios que tiene que cocinar no son, afortunadamente, frontales y centrales. etapa en la versión de sintaxis de consulta - son de fondo. Fuera de mi caja de jabón ahora, de todos modos, gracias por la pregunta. :)
mira este código de muestra de mi proyecto
public static IList<Letter> GetDepartmentLettersLinq(int departmentId)
{
IEnumerable<Letter> allDepartmentLetters =
from allLetter in LetterService.GetAllLetters()
join allUser in UserService.GetAllUsers() on allLetter.EmployeeID equals allUser.ID into usersGroup
from user in usersGroup.DefaultIfEmpty()// here is the tricky part
join allDepartment in DepartmentService.GetAllDepartments() on user.DepartmentID equals allDepartment.ID
where allDepartment.ID == departmentId
select allLetter;
return allDepartmentLetters.ToArray();
}
en este código me uní a 3 tablas y participé en una condición de unión desde donde cláusula
nota: las clases de Servicios simplemente están deformadas (encapsulan) las operaciones de la base de datos
public ActionResult Index()
{
List<CustomerOrder_Result> obj = new List<CustomerOrder_Result>();
var orderlist = (from a in db.OrderMasters
join b in db.Customers on a.CustomerId equals b.Id
join c in db.CustomerAddresses on b.Id equals c.CustomerId
where a.Status == "Pending"
select new
{
Customername = b.Customername,
Phone = b.Phone,
OrderId = a.OrderId,
OrderDate = a.OrderDate,
NoOfItems = a.NoOfItems,
Order_amt = a.Order_amt,
dis_amt = a.Dis_amt,
net_amt = a.Net_amt,
status=a.Status,
address = c.address,
City = c.City,
State = c.State,
Pin = c.Pin
}) ;
foreach (var item in orderlist)
{
CustomerOrder_Result clr = new CustomerOrder_Result();
clr.Customername=item.Customername;
clr.Phone = item.Phone;
clr.OrderId = item.OrderId;
clr.OrderDate = item.OrderDate;
clr.NoOfItems = item.NoOfItems;
clr.Order_amt = item.Order_amt;
clr.net_amt = item.net_amt;
clr.address = item.address;
clr.City = item.City;
clr.State = item.State;
clr.Pin = item.Pin;
clr.status = item.status;
obj.Add(clr);
}