简体   繁体   English

如何在 LINQ lambda 中执行多个表之间的联接

[英]How to perform Join between multiple tables in LINQ lambda

I am trying to perform a Join between multiple tables in LINQ.我正在尝试在 LINQ 中的多个表之间执行联接。 I have the following classes:我有以下课程:

Product {Id, ProdName, ProdQty}

Category {Id, CatName}

ProductCategory{ProdId, CatId} //association table

And I use the following code (where product , category and productcategory are instances of the above classes):我使用以下代码(其中productcategoryproductcategory是上述类的实例):

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

With this code I obtain an object from the following class:使用此代码,我从以下 class 获得 object:

QueryClass { productproductcategory, category}

Where producproductcategory is of type:其中 productproductcategory 的类型为:

ProductProductCategoryClass {product, productcategory}

I do not understand where the joined "table" is, I was expecting a single class that contains all the properties from the involved classes.我不明白加入的“表”在哪里,我期待一个包含所涉及类的所有属性的单个 class

My aim is to populate another object with some properties resulting from the query:我的目标是用查询产生的一些属性填充另一个 object:

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

how can I achieve this goal?我怎样才能实现这个目标?

For joins, I strongly prefer query-syntax for all the details that are happily hidden (not the least of which are the transparent identifiers involved with the intermediate projections along the way that are apparent in the dot-syntax equivalent). 对于连接,我强烈希望查询语法用于所有被愉快隐藏的细节(其中最重要的是与中间投影相关的透明标识符,这在点语法等效中是显而易见的)。 However, you asked regarding Lambdas which I think you have everything you need - you just need to put it all together. 但是,你问过Lambdas我觉得你有你需要的一切 - 你只需要把它们放在一起。

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

If you need to, you can save the join into a local variable and reuse it later, however lacking other details to the contrary, I see no reason to introduce the local variable. 如果需要,可以将连接保存到局部变量中并在以后重用,但是缺少相反的其他细节,我认为没有理由引入局部变量。

Also, you could throw the Select into the last lambda of the second Join (again, provided there are no other operations that depend on the join results) which would give: 此外,您可以将Select抛出到第二个Join的最后一个lambda中(同样,如果没有其他操作依赖于连接结果),这将给出:

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

...and making a last attempt to sell you on query syntax, this would look like this: ...并且最后尝试以查询语法推销您,这看起来像这样:

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

Your hands may be tied on whether query-syntax is available. 您的手可能与查询语法是否可用有关。 I know some shops have such mandates - often based on the notion that query-syntax is somewhat more limited than dot-syntax. 我知道一些商店有这样的要求 - 通常基于查询语法比点语法更有限的概念。 There are other reasons, like "why should I learn a second syntax if I can do everything and more in dot-syntax?" 还有其他原因,比如“如果我可以用点语法做更多的事情,我为什么要学习第二种语法?” As this last part shows - there are details that query-syntax hides that can make it well worth embracing with the improvement to readability it brings: all those intermediate projections and identifiers you have to cook-up are happily not front-and-center-stage in the query-syntax version - they are background fluff. 正如最后一部分所示 - 有一些细节,查询语法隐藏,它可以使它带来的可读性的改进非常值得拥抱:你必须做的所有那些中间预测和标识符很高兴不是前端和中心 - 在查询语法版本中的阶段 - 它们是背景绒毛。 Off my soap-box now - anyhow, thanks for the question. 现在离开我的肥皂盒 - 无论如何,谢谢你的问题。 :) :)

What you've seen is what you get - and it's exactly what you asked for, here: 你所看到的就是你得到的 - 这正是你所要求的,这里:

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

That's a lambda expression returning an anonymous type with those two properties. 这是一个lambda表达式,返回带有这两个属性的匿名类型。

In your CategorizedProducts, you just need to go via those properties: 在您的CategorizedProducts中,您只需要通过这些属性:

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

take look at this sample code from my project 从我的项目中查看此示例代码

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 this code I joined 3 tables and I spited join condition from where clause 在这段代码中,我加入了3个表,然后我从where子句中吐出了join条件

note: the Services classes are just warped(encapsulate) the database operations 注意:Services类只是扭曲(封装)数据库操作

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



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

it has been a while but my answer may help someone: 它已经有一段时间但我的回答可能会帮助某人:

if you already defined the relation properly you can use this: 如果您已经正确定义了关系,可以使用:

        var res = query.Products.Select(m => new
        {
            productID = product.Id,
            categoryID = m.ProductCategory.Select(s => s.Category.ID).ToList(),
        }).ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM