wake-up-neo.com

Durchführen eines Joins zwischen mehreren Tabellen in LINQ Lambda

Ich versuche ein Join zwischen mehreren Tabellen in LINQ auszuführen. Ich habe folgende Kurse:

Product {Id, ProdName, ProdQty}

Category {Id, CatName}

ProductCategory{ProdId, CatId} //association table

Und ich benutze den folgenden Code (wobei product, category und productcategory Instanzen der obigen Klassen sind):

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

Mit diesem Code erhalte ich ein Objekt aus folgender Klasse:

QueryClass { productproductcategory, category}

Wo die Produktkategorie vom Typ ist:

ProductProductCategoryClass {product, productcategory}

Ich verstehe nicht, wo sich die verknüpfte "Tabelle" befindet. Ich habe ein einzelne Klasse erwartet, das alle Eigenschaften der beteiligten Klassen enthält.

Mein Ziel ist es, ein anderes Objekt mit einigen Eigenschaften zu füllen, die sich aus der Abfrage ergeben:

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

wie kann ich dieses Ziel erreichen?

81
CiccioMiami

Für Joins bevorzuge ich stark die Abfragesyntax für alle Details, die gut versteckt sind (nicht zuletzt die transparenten Bezeichner, die mit den Zwischenprojektionen auf dem Weg verbunden sind, die im Punktsyntaxäquivalent ersichtlich sind). Sie fragten jedoch nach Lambdas, von denen ich glaube, dass Sie alles haben, was Sie brauchen - Sie müssen nur alles zusammenstellen.

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

Wenn nötig, können Sie den Join in einer lokalen Variablen speichern und später wiederverwenden. Da jedoch andere Details fehlen, sehe ich keinen Grund, die lokale Variable einzuführen.

Sie können auch Select in das letzte Lambda des zweiten Join werfen (vorausgesetzt, es gibt keine anderen Operationen, die von den Verknüpfungsergebnissen abhängen), die Folgendes ergeben:

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

... und einen letzten Versuch unternehmend, Sie über die Abfragesyntax zu verkaufen, würde dies so aussehen:

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

Es kann sein, dass Sie nicht sicher sind, ob die Abfragesyntax verfügbar ist. Ich weiß, dass einige Geschäfte solche Mandate haben - oft basierend auf der Vorstellung, dass die Abfragesyntax etwas eingeschränkter ist als die Punktsyntax. Es gibt andere Gründe, wie "Warum sollte ich eine zweite Syntax lernen, wenn ich alles und mehr in Punktsyntax machen kann?" Wie dieser letzte Teil zeigt - gibt es Details, die die Abfragesyntax verbirgt, die es lohnenswert machen, sich mit der Verbesserung der Lesbarkeit auseinanderzusetzen: Alle Zwischenprojektionen und Bezeichner, die Sie erstellen müssen, sind glücklicherweise nicht im Vordergrund. Stufe in der Query-Syntax-Version - sie sind Hintergrund Flaum. Verschwinde jetzt aus meiner Seifenkiste - jedenfalls danke für die Frage. :)

161
devgeezer

Sie haben gesehen, was Sie bekommen - und genau danach haben Sie gefragt, hier:

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

Dies ist ein Lambda-Ausdruck, der einen anonymen Typ mit diesen beiden Eigenschaften zurückgibt.

In Ihren kategorisierten Produkten müssen Sie nur die folgenden Eigenschaften aufrufen:

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

schauen Sie sich diesen Beispielcode aus meinem Projekt an

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

in diesem Code habe ich 3 Tabellen verbunden und die Join-Bedingung aus der where-Klausel heraus ausgespuckt

hinweis: Die Services-Klassen sind nur die Datenbankoperationen verzerrt (gekapselt)

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



       }
1

es ist schon eine Weile her, aber meine Antwort könnte jemandem helfen:

wenn Sie die Beziehung bereits richtig definiert haben, können Sie dies verwenden:

        var res = query.Products.Select(m => new
        {
            productID = product.Id,
            categoryID = m.ProductCategory.Select(s => s.Category.ID).ToList(),
        }).ToList();
0
iDeveloper
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}");
        }
0
Alex Martinez