我试图在LINQ中的 多个表之间 执行 联接 。我有以下课程:
Product {Id, ProdName, ProdQty} Category {Id, CatName} ProductCategory{ProdId, CatId} //association table
我用下面的代码(其中product,category和productcategory是在上述类的实例):
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}
生产产品类别为:
ProductProductCategoryClass {product, productcategory}
我不明白联接的“表”在哪里,我期望有 一个 包含所涉及类的所有属性的类。
我的目标是使用查询产生的一些属性填充另一个对象:
CategorizedProducts catProducts = query.Select(m => new { m.ProdId = ???, m.CatId = ???, //other assignments });
我怎样才能实现这个目标?
对于联接,我强烈希望对所有隐藏的细节使用查询语法(并非最不重要的是中间投影所涉及的透明标识符,在点语法等效项中很明显)。但是,您询问了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 { ppc, c }) .Select(m => new { ProdId = m.ppc.p.Id, // or m.ppc.pc.ProdId CatId = m.c.CatId // other assignments });
如果需要,可以将联接保存到局部变量中,并在以后重用,但是由于缺少其他细节,我认为没有必要引入局部变量。
同样,您可以将s Select放入第二个的最后一个lambda中Join(再次,只要没有其他依赖于联接结果的操作),它将得出:
Select
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 });
…并最后尝试通过查询语法向您推销,看起来像这样:
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 };
您的双手可能会被束缚在查询语法是否可用上。我知道有些商店有这样的要求- 通常是基于查询语法比点语法受限制的观点。还有其他原因,例如“如果我可以用点语法做更多的事情,为什么还要学习第二种语法?” 正如最后一部分所展示的那样- 查询语法隐藏的细节可以使其值得一读,因为它带来了可读性的提高:所有必须准备的中间投影和标识符都不是正面而居中的语法版本中的阶段- 它们是背景绒毛。现在关闭我的肥皂盒-不管怎样,谢谢您的提问。:)