C# Linq到实体连接与组连接

C# Linq到实体连接与组连接,c#,linq,linq-to-entities,C#,Linq,Linq To Entities,我在网上搜索过,但仍然找不到简单的答案。有人能用简单的英语解释一下GroupJoin是什么吗?它与常规内部联接有何不同?它常用吗?它是否仅用于方法语法?查询语法呢?一个c代码示例会很好 根据: 了解GroupJoin的最佳方法是思考 参加在那里,我们的总体想法是通过外部 输入序列,从内部序列中找到所有匹配项 基于每个序列上的密钥投影,然后生成成对的 匹配元素。GroupJoin与此类似,只是 它产生成对的元素,为每个外部元素产生一个结果 基于该项目和匹配内部项目的顺序的项目 唯一的区别在于返回语

我在网上搜索过,但仍然找不到简单的答案。有人能用简单的英语解释一下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语法表示它不类似于外部联接,而是左外部联接。我想我应该指定平面外部联接是左外部联接。解释得很好,我现在明白了