Comment effectuer une jointure entre plusieurs tables dans LINQ lambda

J’essaie d’effectuer une jointure entre plusieurs tables dans LINQ. J’ai les classes suivantes:

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

Et j’utilise le code suivant (où product , category et productcategory sont des instances des classes ci-dessus):

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

Avec ce code, j’obtiens un object de la classe suivante:

 QueryClass { productproductcategory, category} 

Où productproductcategory est de type:

 ProductProductCategoryClass {product, productcategory} 

Je ne comprends pas où se trouve la “table” jointe, je m’attendais à une seule classe contenant toutes les propriétés des classes impliquées.

Mon but est de remplir un autre object avec certaines propriétés résultant de la requête:

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

Comment puis-je atteindre cet objective?

Pour les jointures, je préfère fortement la syntaxe de requête pour tous les détails qui sont heureusement cachés (les identifiants transparents impliqués dans les projections intermédiaires sur le chemin apparaissant dans l’équivalent de la syntaxe point par point). Cependant, vous avez demandé à propos de Lambdas que je pense que vous avez tout ce dont vous avez besoin – il vous suffit de tout rassembler.

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

Si vous en avez besoin, vous pouvez enregistrer la jointure dans une variable locale et la réutiliser plus tard. Cependant, en l’absence d’autres détails, je ne vois aucune raison d’introduire la variable locale.

En outre, vous pouvez lancer la Select dans le dernier lambda de la deuxième Join (à nouveau, à condition qu’aucune autre opération ne dépende des résultats de la jointure), ce qui donnerait:

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

… et faire une dernière tentative pour vous vendre sur la syntaxe de requête, cela ressemblerait à ceci:

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

Vos mains peuvent être liées si la syntaxe de requête est disponible. Je sais que certains magasins ont de tels mandats – souvent basés sur la notion que la syntaxe de requête est un peu plus limitée que la syntaxe à point. Il y a d’autres raisons, comme “pourquoi devrais-je apprendre une seconde syntaxe si je peux tout faire et plus dans la syntaxe à point?” Comme le montre cette dernière partie – il y a des détails que la syntaxe de la requête cache peut faire valoir avec l’amélioration de la lisibilité qu’elle apporte: toutes les projections intermédiaires et tous les identifiants que vous devez préparer ne sont heureusement pas étape dans la version query-syntax – ils sont des fluff d’arrière-plan. Hors de ma boîte à soap maintenant – de toute façon, merci pour la question. 🙂

Ce que vous avez vu est ce que vous obtenez – et c’est exactement ce que vous avez demandé, ici:

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

C’est une expression lambda renvoyant un type anonyme avec ces deux propriétés.

Dans vos produits classés, il vous suffit de passer par ces propriétés:

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

jetez un coup d’oeil à cet exemple de code de mon projet

 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 sortingcky part join allDepartment in DepartmentService.GetAllDepartments() on user.DepartmentID equals allDepartment.ID where allDepartment.ID == departmentId select allLetter; return allDepartmentLetters.ToArray(); } 

dans ce code je me suis joint à 3 tables et j’ai envoyé des conditions de jointure à partir de la clause where

note: les classes de services sont simplement déformées (encapsulent) les opérations de firebase 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}"); }