Como executar Join entre várias tabelas no LINQ lambda

Eu estou tentando executar uma associação entre várias tabelas no LINQ. Eu tenho as seguintes classs:

Product {Id, ProdName, ProdQty} Category {Id, CatName} ProductCategory{ProdId, CatId} //association table 

E eu uso o seguinte código (onde product , category e productcategory são instâncias das classs acima):

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

Com este código eu obtenho um object da seguinte class:

 QueryClass { productproductcategory, category} 

Onde producproductcategory é do tipo:

 ProductProductCategoryClass {product, productcategory} 

Eu não entendo onde a “mesa” unida é, eu estava esperando uma única class que contém todas as propriedades das classs envolvidas.

Meu objective é preencher outro object com algumas propriedades resultantes da consulta:

 CategorizedProducts catProducts = query.Select(m => new { m.ProdId = ???, m.CatId = ???, //other assignments }); 

Como posso alcançar esse objective?

   

Para junções, eu prefiro fortemente a syntax de consulta para todos os detalhes que estão felizes escondidos (não menos do que são os identificadores transparentes envolvidos com as projeções intermediárias ao longo do caminho que são aparentes no equivalente da syntax de pontos). No entanto, você perguntou sobre Lambdas que eu acho que você tem tudo que você precisa – você só precisa colocar tudo 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 = mcCatId // other assignments }); 

Se você precisar, você pode salvar a junit em uma variável local e reutilizá-lo mais tarde, no entanto, faltando outros detalhes em contrário, não vejo razão para introduzir a variável local.

Além disso, você poderia jogar o Select no último lambda do segundo Join (novamente, desde que não haja outras operações que dependam dos resultados da junit) que dariam:

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

… e fazendo uma última tentativa de vendê-lo na syntax de consulta, ficaria assim:

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

Suas mãos podem estar ligadas se a syntax de consulta está disponível. Eu sei que algumas lojas têm tais mandatos – geralmente baseados na noção de que a syntax de consulta é um pouco mais limitada que a syntax de ponto. Há outras razões, como “por que eu deveria aprender uma segunda syntax se eu puder fazer tudo e mais na syntax de pontos?” Como esta última parte mostra – há detalhes que a syntax de consulta esconde que podem fazer com que valha a pena ser incluída com a melhoria da legibilidade: todas as projeções intermediárias e identificadores que você precisa preparar não são alegres. estágio na versão de syntax de consulta – eles são fluff de plano de fundo. Fora da minha checkbox de soap agora – de qualquer forma, obrigado pela pergunta. 🙂

O que você viu é o que você obtém – e é exatamente o que você pediu, aqui:

 (ppc, c) => new { productproductcategory = ppc, category = c} 

Essa é uma expressão lambda que retorna um tipo anônimo com essas duas propriedades.

Em seus produtos categorizados, você só precisa passar por essas propriedades:

 CategorizedProducts catProducts = query.Select( m => new { ProdId = m.productproductcategory.product.Id, CatId = m.category.CatId, // other assignments }); 

dê uma olhada neste exemplo de código do meu projeto

 public static IList GetDepartmentLettersLinq(int departmentId) { IEnumerable 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(); } 

Neste código eu entrei 3 tabelas e eu spited condição de junit de cláusula where

Nota: as classs Services são apenas deformadas (encapsulam) as operações do database

  public ActionResult Index() { List obj = new List(); 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); } 
 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}"); }