C# Linq到实体连接与组连接
我在网上搜索过,但仍然找不到简单的答案。有人能用简单的英语解释一下GroupJoin是什么吗?它与常规内部联接有何不同?它常用吗?它是否仅用于方法语法?查询语法呢?一个c代码示例会很好 根据: 了解GroupJoin的最佳方法是思考 参加在那里,我们的总体想法是通过外部 输入序列,从内部序列中找到所有匹配项 基于每个序列上的密钥投影,然后生成成对的 匹配元素。GroupJoin与此类似,只是 它产生成对的元素,为每个外部元素产生一个结果 基于该项目和匹配内部项目的顺序的项目 唯一的区别在于返回语句: 加入: 群组加入:C# Linq到实体连接与组连接,c#,linq,linq-to-entities,C#,Linq,Linq To Entities,我在网上搜索过,但仍然找不到简单的答案。有人能用简单的英语解释一下GroupJoin是什么吗?它与常规内部联接有何不同?它常用吗?它是否仅用于方法语法?查询语法呢?一个c代码示例会很好 根据: 了解GroupJoin的最佳方法是思考 参加在那里,我们的总体想法是通过外部 输入序列,从内部序列中找到所有匹配项 基于每个序列上的密钥投影,然后生成成对的 匹配元素。GroupJoin与此类似,只是 它产生成对的元素,为每个外部元素产生一个结果 基于该项目和匹配内部项目的顺序的项目 唯一的区别在于返回语
Console.WriteLine(
people.GroupJoin(
records,
x => x.Email,
y => y.Mail,
(person, recs) => new {
Name = person.Name,
SlackIds = recs.Select(r => r.SlackId).ToArray() // You could materialize //whatever way you want.
}
));
请在此处阅读更多信息:
行为
假设您有两个列表:
Id Value
1 A
2 B
3 C
Id ChildValue
1 a1
1 a2
1 a3
2 b1
2 b2
将Id字段上的两个列表合并后,结果将是:
Value ChildValue
A a1
A a2
A a3
B b1
B b2
Value ChildValues
A [a1, a2, a3]
B [b1, b2]
C []
将Id字段上的两个列表组合在一起时,结果将是:
Value ChildValue
A a1
A a2
A a3
B b1
B b2
Value ChildValues
A [a1, a2, a3]
B [b1, b2]
C []
所以Join生成父值和子值的平面表格结果。
GroupJoin在第一个列表中生成一个条目列表,每个条目在第二个列表中都有一组已联接的条目
这就是为什么Join在SQL中与内部Join等价:C没有条目。而GroupJoin与外部Join等价:C在结果集中,但如果SQL结果集中的相关条目列表为空,则会有一行C-null
语法
让这两个列表分别为IEnumerable和IEnumerable。对于Linq to实体:IQueryable
连接语法将是
来自父级中的p
在p.Id等于c.Id的子对象中加入c
选择新的{p.Value,c.ChildValue}
返回IEnumerable,其中X是具有两个属性的匿名类型,即Value和ChildValue。此查询语法使用隐藏的方法
GroupJoin语法将是
来自父级中的p
将c与p.Id上的Child连接,等于c.Id与g
选择新{Parent=p,Children=g}
返回IEnumerable,其中Y是一个匿名类型,由一个Parent类型的属性和一个IEnumerable类型的属性组成。此查询语法使用隐藏的方法
我们可以在后一个查询中选择g,它将选择一个IEnumerable,比如一个列表。在许多情况下,包含父项的select更有用
一些用例
1.产生扁平的外部连接。
如前所述,声明
来自父级中的p
将c与p.Id上的Child连接,等于c.Id与g
选择新{Parent=p,Children=g}
。。。生成包含子组的父组列表。通过两个小的添加,可以将其转换为父子对的平面列表:
来自父母的p
将p.Id等于c.Id的子对象中的c连接到g//Id.Containsp.Id;
。。。父母的顺序将决定结果。如果父项按Id排序,则结果将是父项2、3、4、7。不好的。但是,我们也可以使用join来过滤列表。通过使用ID作为第一个列表,将保留顺序:
从id中的id
在id等于p.id的父节点中加入p
选择p
结果是家长3、7、2、4。假设您有两个不同的班级:
public class Person
{
public string Name, Email;
public Person(string name, string email)
{
Name = name;
Email = email;
}
}
现在,让我们准备要使用的数据:
var people = new Person[]
{
new Person("Sudi", "sudi@try.cd"),
new Person("Simba", "simba@try.cd"),
new Person("Sarah", string.Empty)
};
var records = new Data[]
{
new Data("sudi@try.cd", "Sudi_Try"),
new Data("sudi@try.cd", "Sudi@Test"),
new Data("simba@try.cd", "SimbaLion")
};
你会注意到sudi@try.cd他有两个懒虫。我这样做是为了演示如何
参加工作
现在,让我们构造查询以将Person与数据连接起来:
var query = people.Join(records,
x => x.Email,
y => y.Mail,
(person, record) => new { Name = person.Name, SlackId = record.SlackId});
Console.WriteLine(query);
构造查询后,还可以使用foreach对其进行迭代,如下所示:
foreach (var item in query)
{
Console.WriteLine($"{item.Name} has Slack ID {item.SlackId}");
}
我们还将输出GroupJoin的结果:
Console.WriteLine(
people.GroupJoin(
records,
x => x.Email,
y => y.Mail,
(person, recs) => new {
Name = person.Name,
SlackIds = recs.Select(r => r.SlackId).ToArray() // You could materialize //whatever way you want.
}
));
您会注意到GroupJoin将把所有SlackId放在一个组中。根据MSDN,group join是一个带有into表达式的join子句。有更多信息和代码示例。它本质上是一个内部连接,如果右侧的元素与左侧的元素不匹配,则会得到一个空结果;但是结果被组织成组。因此在GroupJoin中,子值将包含对象,包含相关值的吗?正如您所说,GroupJoin类似于外部联接,但group join的纯linq语法表示它不类似于外部联接,而是左外部联接。我想我应该指定平面外部联接是左外部联接。解释得很好,我现在明白了