Seven 连接运算 将两个数据源“联接”就是将一个数据源中的对象与另一个数据源中共享某个通用特性的对象关联起来。 LINQ 框架中提供的联接方法包括 Join 和 GroupJoin。这些方法执行同等联接,即根据两个数据源的键是否相等来匹配这两个数据源的联接。 (与此相较,Transact-SQL 支持除“等于”之外的联接运算符,例如,“小于”运算符。)用关系数据库术语表达,就是说Join 实现了内部联接,这种联接只返回那些在另一个数据集中具有匹配项的对象。The GroupJoin 方法在关系数据库术语中没有直接的等效项,但它实现了内部联接和左外部联接的超集。左外部联接是这样一种联接:它返回第一个(左)数据源的每个元素,即使该元素在另一个数据源中没有关联元素。
方法 | | | | | Join | | Join … in … on … equals … | Enumerable.Join
Queryable.Join
| | GroupJoin | 根据键选择器函数联接两个序列,并对每个元素的结果匹配项进行分组。 | join … in … on … equals … into … | Enumerable.GroupJoin
Queryable.GroupJoin
| |
内部连接 varinnerJoinQuery = from category incategories join prod in productson category.ID equalsprod.CategoryID select new {ProductName = prod.Name, Category = category.Name }; 含有into 表达式的 join 子句称为分组联接。 varinnerGroupJoinQuery = from category incategories join prod in productson category.ID equalsprod.CategoryID into prodGroup select new {CategoryName = category.Name, Products = prodGroup }; 分组联接会产生一个分层的结果序列,该序列将左侧源序列中的元素与右侧源序列中的一个或多个匹配元素相关联。 分组联接没有等效的关系术语;它本质上是一个对象数组序列。如果在右侧源序列中找不到与左侧源中的元素相匹配的元素,则 join 子句会为该项产生一个空数组。 因此,分组联接基本上仍然是一种内部同等联接,区别只在于分组联接将结果序列组织为多个组。
还可以将分组联接的结果用作其他子查询的生成器: varinnerGroupJoinQuery2 = from category incategories join prod in productson category.ID equalsprod.CategoryID into prodGroup from prod2 inprodGroup where prod2.UnitPrice > 2.50M select prod2; 左外部链接 在 LINQ 中执行左外部联接,请将DefaultIfEmpty 方法与分组联接结合起来,以指定要在某个左侧元素不具有匹配元素时产生的默认右侧元素。可以使用null 作为任何引用类型的默认值,也可以指定用户定义的默认类型。下面的示例演示了用户定义的默认类型: varleftOuterJoinQuery = from category incategories join prod in productson category.ID equalsprod.CategoryID into prodGroup from item inprodGroup.DefaultIfEmpty(new Product{Name =String.Empty, CategoryID = 0}) select new { CatName= category.Name, ProdName = item.Name }; equals运算 join 子句执行同等联接。 换句话说,只能基于两个键之间的相等关系进行匹配。 其他类型的比较(例如,“greater than”或“not equals”)不受支持。 为了表明所有联接都是同等联接,join 子句使用 equals 关键字而不是 == 运算符。 equals 关键字只能用在 join 子句中,并且它与 == 运算符之间存在一个重要区别。 对于 equals,左键使用外部源序列,而右键使用内部源序列。 外部源仅在 equals 的左侧位于范围内,而内部源序列仅在其右侧位于范围内。
|