如何在LINQ lambda中的多个表之间执行连接
我正尝试在LINQ中的多个表之间执行联接 。 我有以下类:
Product {Id, ProdName, ProdQty} Category {Id, CatName} ProductCategory{ProdId, CatId} //association table
我使用下面的代码(其中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});
通过这段代码,我从下面的类中获得一个对象:
QueryClass { productproductcategory, category}
其中producproductcategory是types的:
ProductProductCategoryClass {product, productcategory}
我不明白join的“表”在哪里,我期待一个包含所有涉及类的属性的类。
我的目标是用查询产生的一些属性填充另一个对象:
CategorizedProducts catProducts = query.Select(m => new { m.ProdId = ???, m.CatId = ???, //other assignments });
我怎样才能达到这个目标?
对于连接,我非常喜欢查询语法,所有的细节都被隐藏起来(其中不乏中间投影所涉及的透明标识符,这些标识符相当于点语法)。 然而,你问到关于兰巴达斯,我认为你有你需要的一切 – 你只需要把它放在一起。
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 });
如果需要的话,可以把连接保存到一个局部variables中,稍后重用,但是缺less其他细节,我没有理由引入局部variables。
另外,你可以将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 };
你的手可能是绑定在查询语法是否可用。 我知道一些商店有这样的规定 – 通常基于这样的概念,即查询语法比点语法更有限。 还有其他一些原因,比如“为什么我应该学习第二种语法,如果我能用点语法来做所有事情?” 正如最后一部分所显示的那样 – 有些查询语法隐藏的细节可以使其值得接受,因为它带来了可读性的提高:所有那些中间的预测和标识符都是非常适合的,在查询语法版本的阶段 – 他们是背景绒毛。 不pipe怎么样,谢谢你的提问。 🙂
你所看到的是你所得到的 – 这正是你所要求的,在这里:
(ppc, c) => new { productproductcategory = ppc, category = c}
这是一个lambdaexpression式,返回具有这两个属性的匿名types。
在您的CategorizedProducts中,您只需要通过这些属性:
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(); }
在这段代码中,我join了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); }