JOINS
连接用于组合通过公共密钥保存数据的不同列表或表。
与 SQL 一样,LINQ 支持以下类型的连接:
内部,左侧,右侧,交叉和完整外部连接。
以下示例中使用以下两个列表:
var first = new List<string>(){ "a","b","c"}; // Left data
var second = new List<string>(){ "a", "c", "d"}; // Right data
(内部联接
var result = from f in first
join s in second on f equals s
select new { f, s };
var result = first.Join(second,
f => f,
s => s,
(f, s) => new { f, s });
// Result: {"a","a"}
// {"c","c"}
左外连接
var leftOuterJoin = from f in first
join s in second on f equals s into temp
from t in temp.DefaultIfEmpty()
select new { First = f, Second = t};
// Or can also do:
var leftOuterJoin = from f in first
from s in second.Where(x => x == f).DefaultIfEmpty()
select new { First = f, Second = s};
// Result: {"a","a"}
// {"b", null}
// {"c","c"}
// Left outer join method syntax
var leftOuterJoinFluentSyntax = first.GroupJoin(second,
f => f,
s => s,
(f, s) => new { First = f, Second = s })
.SelectMany(temp => temp.Second.DefaultIfEmpty(),
(f, s) => new { First = f.First, Second = s });
正确的外部加入
var rightOuterJoin = from s in second
join f in first on s equals f into temp
from t in temp.DefaultIfEmpty()
select new {First=t,Second=s};
// Result: {"a","a"}
// {"c","c"}
// {null,"d"}
交叉加入
var CrossJoin = from f in first
from s in second
select new { f, s };
// Result: {"a","a"}
// {"a","c"}
// {"a","d"}
// {"b","a"}
// {"b","c"}
// {"b","d"}
// {"c","a"}
// {"c","c"}
// {"c","d"}
完全外部加入
var fullOuterjoin = leftOuterJoin.Union(rightOuterJoin);
// Result: {"a","a"}
// {"b", null}
// {"c","c"}
// {null,"d"}
实际的例子
上面的示例有一个简单的数据结构,因此你可以专注于从技术上理解不同的 LINQ 连接,但在现实世界中,你将拥有需要加入的列的表。
在下面的示例中,只使用了一个类 Region
,实际上你将连接两个或多个具有相同键的不同表(在此示例中,first
和 second
通过公共密钥 ID
连接)。
示例: 请考虑以下数据结构:
public class Region
{
public Int32 ID;
public string RegionDescription;
public Region(Int32 pRegionID, string pRegionDescription=null)
{
ID = pRegionID; RegionDescription = pRegionDescription;
}
}
现在准备数据(即填充数据):
// Left data
var first = new List<Region>()
{ new Region(1), new Region(3), new Region(4) };
// Right data
var second = new List<Region>()
{
new Region(1, "Eastern"), new Region(2, "Western"),
new Region(3, "Northern"), new Region(4, "Southern")
};
你可以看到,在此示例中,first
不包含任何区域描述,因此你希望从 second
加入它们。然后内连接看起来像:
// do the inner join
var result = from f in first
join s in second on f.ID equals s.ID
select new { f.ID, s.RegionDescription };
// Result: {1,"Eastern"}
// {3, Northern}
// {4,"Southern"}
这个结果动态创建了匿名对象,这很好,但我们已经创建了一个合适的类 - 所以我们可以指定它:我们可以说 select new { f.ID, s.RegionDescription };
而不是 select new Region(f.ID, s.RegionDescription);
,它会返回相同的数据,但会创建 Region
类型的对象 - 这将保持与其他对象的兼容性。