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

时间:2012-03-15 13:00:06

标签: c# linq join lambda multiple-tables

我正在尝试在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}

其中producproductcategory的类型为:

ProductProductCategoryClass {product, productcategory}

我不明白加入的“表”在哪里,我期待一个单个类,其中包含所涉及类的所有属性。

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

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

我该如何实现这一目标?

6 个答案:

答案 0 :(得分:156)

对于连接,我更喜欢查询语法用于所有被愉快隐藏的细节(其中最重要的是与中间投影一起使用的透明标识符,这在点语法等效中很明显)。但是,你问过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
    };

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

答案 1 :(得分:10)

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

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

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

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

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

答案 2 :(得分:4)

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

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子句

中吐出了连接条件

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

答案 3 :(得分:1)

ImageButton.setImageBitmap(bm);

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

如果您已经正确定义了关系,则可以使用以下方法:

4.033327383481244   255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
4.066660667642246   255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
4.099993951803248
4.13332723596425    255 255 255
4.166660520125252   255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
4.199993804286254   255 255 255 255 255 255 255 255 255 255 255 255 255