Как выполнить соединение между несколькими таблицами в LINQ lambda
Я пытаюсь выполнить Соединение между несколькими таблицами в LINQ. У меня есть следующие классы:
Product {Id, ProdName, ProdQty}
Category {Id, CatName}
ProductCategory{ProdId, CatId} //association table
И я использую следующий код (где product
, category
и productcategory
являются экземплярами вышеуказанных классов):
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});
С помощью этого кода я получаю объект из следующего класса:
QueryClass { productproductcategory, category}
Где производственная категория относится к типу:
ProductProductCategoryClass {product, productcategory}
Я не понимаю, где объединенная "таблица", я ожидал single class, который содержит все свойства из вовлеченных классов.
Моя цель - заполнить другой объект некоторыми свойствами, полученными в результате запроса:
CategorizedProducts catProducts = query.Select(m => new { m.ProdId = ???, m.CatId = ???, //other assignments });
Как я могу достичь этой цели?
Ответы
Ответ 1
Для объединений я настоятельно предпочитаю синтаксис запроса для всех деталей, которые счастливо скрыты (не последним из которых являются прозрачные идентификаторы, связанные с промежуточными проекциями, на пути, которые очевидны в эквиваленте точки-синтаксиса). Однако вы спросили насчет Лямбдаса, который, я думаю, у вас есть все, что вам нужно - вам просто нужно собрать все это вместе.
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
});
Если вам нужно, вы можете сохранить соединение в локальной переменной и повторно использовать его позже, однако, не имея других деталей, наоборот, я не вижу причин для введения локальной переменной.
Кроме того, вы можете выбросить Select
в последнюю лямбда второй Join
(опять же, если нет других операций, зависящих от результатов объединения), которые дадут:
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
});
... и сделав последнюю попытку продать вас на синтаксисе запроса, это будет выглядеть так:
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
};
Ваши руки могут быть связаны с наличием синтаксиса запроса. Я знаю, что некоторые магазины имеют такие мандаты - часто на основе понятия, что синтаксис запроса несколько более ограничен, чем точечный синтаксис. Есть и другие причины, такие как "зачем мне изучать второй синтаксис, если я могу делать все и многое другое в точечном синтаксисе?" Как показывает эта последняя часть - есть детали, которые скрывают синтаксис запросов, которые могут сделать его достойным охвата с улучшением читаемости, которое он приносит: все те промежуточные проекции и идентификаторы, которые вы должны готовить, к счастью не относятся к фронту и центру, этап в синтаксисе запроса - они являются фоном. Теперь с моего мыльного ящика - во всяком случае, спасибо за вопрос.:)
Ответ 2
То, что вы видели, это то, что вы получаете - и это именно то, что вы просили, здесь:
(ppc, c) => new { productproductcategory = ppc, category = c}
Это выражение лямбда, возвращающее анонимный тип с этими двумя свойствами.
В ваших категориальных продуктах вам просто нужно пройти через эти свойства:
CategorizedProducts catProducts = query.Select(
m => new {
ProdId = m.productproductcategory.product.Id,
CatId = m.category.CatId,
// other assignments
});
Ответ 3
взгляните на этот образец кода из моего проекта
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();
}
в этом коде я присоединился к 3 таблицам, и я включил условие соединения из условия where
note: классы Services просто деформируются (инкапсулируют) операции с базой данных
Ответ 4
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);
}
Ответ 5
var query = from a in d.tbl_Usuarios
from b in d.tblComidaPreferidas
from c in d.tblLugarNacimientoes
select new
{
_nombre = a.Nombre,
_comida = b.ComidaPreferida,
_lNacimiento = c.Ciudad
};
foreach (var i in query)
{
Console.WriteLine($"{i._nombre } le gusta {i._comida} y nació en {i._lNacimiento}");
}
Ответ 6
это было давно, но мой ответ может кому-то помочь:
если вы уже правильно определили отношение, вы можете использовать это:
var res = query.Products.Select(m => new
{
productID = product.Id,
categoryID = m.ProductCategory.Select(s => s.Category.ID).ToList(),
}).ToList();