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

本文关键字:之间 执行 Join LINQ lambda | 更新日期: 2023-09-27 18:27:49

我正试图在LINQ中执行多个表之间的联接。我有以下课程:

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

我使用以下代码(其中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});

使用此代码,我从以下类中获得一个对象:

QueryClass { productproductcategory, category}

产品类别属于以下类型:

ProductProductCategoryClass {product, productcategory}

我不知道联接的"表"在哪里,我希望有一个单个类,它包含所涉及类的所有属性。

我的目标是用查询产生的一些属性填充另一个对象:

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

我该如何实现这个目标?

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

对于联接,我强烈喜欢查询语法来处理所有令人愉快地隐藏的细节(尤其是与中间投影相关的透明标识符,这些标识符在点语法等效中很明显)。然而,你问了关于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
    });

如果需要,您可以将联接保存到一个局部变量中,并在以后重用它,但由于缺乏其他相反的细节,我认为没有理由引入局部变量。

此外,您可以将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
    });

最后一次尝试向您推销查询语法,如下所示:

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

查询语法是否可用可能会让您左右为难。我知道有些商店有这样的规定——通常是基于查询语法比点语法更有限的概念。还有其他原因,比如"如果我能用点语法做所有的事情,为什么我要学习第二种语法?"正如最后一部分所示,查询语法隐藏了一些细节,这些细节可以使它非常值得接受,并提高可读性:你必须编写的所有中间投影和标识符很高兴都不是查询语法版本的前沿和中心——它们是背景绒毛。现在把我的肥皂盒拿开——不管怎样,谢谢你的提问

你所看到的就是你所得到的——这正是你所要求的,在这里:

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

这是一个lambda表达式,返回一个具有这两个属性的匿名类型。

在你的分类产品中,你只需要通过这些属性:

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

看看我的项目中的这个示例代码

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子句中抛出了连接条件

注意:服务类只是扭曲(封装)了数据库操作

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

这已经有一段时间了,但我的答案可能会对某人有所帮助:

如果你已经正确定义了关系,你可以使用这个:

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