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

Cic*_*ami 83 c# linq lambda join multiple-tables

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

Product {Id, ProdName, ProdQty}

Category {Id, CatName}

ProductCategory{ProdId, CatId} //association table
Run Code Online (Sandbox Code Playgroud)

我使用以下代码(其中product,category以及productcategory上述类的实例):

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});
Run Code Online (Sandbox Code Playgroud)

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

QueryClass { productproductcategory, category}
Run Code Online (Sandbox Code Playgroud)

producproductcategory的类型是:

ProductProductCategoryClass {product, productcategory}
Run Code Online (Sandbox Code Playgroud)

我不明白加入的"表"在哪里,我期待一个包含所涉及类的所有属性的单个类.

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

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

我怎样才能实现这个目标?

dev*_*zer 168

对于连接,我强烈希望查询语法用于所有被愉快隐藏的细节(其中最重要的是与中间投影相关的透明标识符,这在点语法等效中是显而易见的).但是,你问过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
    });
Run Code Online (Sandbox Code Playgroud)

如果需要,可以将连接保存到局部变量中并在以后重用,但是缺少相反的其他细节,我认为没有理由引入局部变量.

此外,你可以抛出Select第二个的最后一个lambda Join(再次,如果没有其他依赖于连接结果的操作),它将给出:

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
    });
Run Code Online (Sandbox Code Playgroud)

...并且最后尝试以查询语法推销您,这看起来像这样:

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
    };
Run Code Online (Sandbox Code Playgroud)

您的手可能与查询语法是否可用有关.我知道一些商店有这样的要求 - 通常基于查询语法比点语法更有限的概念.还有其他原因,比如"如果我可以用点语法做更多的事情,我为什么要学习第二种语法?" 正如最后一部分所示 - 有一些细节,查询语法隐藏,它可以使它带来的可读性提高值得拥抱:所有那些你必须做饭的中间预测和标识符很高兴不是前端和中心 - 在查询语法版本中的阶段 - 它们是背景绒毛.现在离开我的肥皂盒 - 无论如何,谢谢你的问题.:)

  • 谢谢你的解决方案更完整.我同意查询语法在某些情况下更清楚,但你猜对了,我被要求使用lambda.此外,我必须在6个表上进行此连接,并且在这种情况下的点符号更加整洁 (3认同)

Jon*_*eet 10

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

(ppc, c) => new { productproductcategory = ppc, category = c}
Run Code Online (Sandbox Code Playgroud)

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

在您的CategorizedProducts中,您只需要通过这些属性:

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


Bas*_*ANI 6

从我的项目中查看此示例代码

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();
}
Run Code Online (Sandbox Code Playgroud)

在这段代码中,我加入了 3 个表,并且从 where 子句中设置了连接条件

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


小智 5

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



       }
Run Code Online (Sandbox Code Playgroud)