c# - Left Outer Join,这两种方法有什么区别?

标签 c# linq left-join

这两种使用 LINQ 执行 Left Outer Join 的方法有什么区别,因为我都使用了两个买家和供应商列表,并按公共(public)区域加入它们以查找同一区域的供应商和买家。

class Supplier
{
    public string Name { get; set; }
    public string District { get; set; }
}

class Buyer
{
    public string Name { get; set; }
    public string District { get; set; }
}
List<Buyer> buyers = new List<Buyer>()
{
    new Buyer() { Name = "Johny", District = "Fantasy District" },
    new Buyer() { Name = "Peter", District = "Scientists District" },
    new Buyer() { Name = "Paul", District = "Fantasy District" },
    new Buyer() { Name = "Maria", District = "Scientists District" },
    new Buyer() { Name = "Joshua", District = "EarthIsFlat District" },
    new Buyer() { Name = "Sylvia", District = "Developers District" },
    new Buyer() { Name = "Rebecca", District = "Scientists District" },
    new Buyer() { Name = "Jaime", District = "Developers District" },
    new Buyer() { Name = "Pierce", District = "Fantasy District" }
};
List<Supplier> suppliers = new List<Supplier>()
{
    new Supplier() { Name = "Harrison", District = "Fantasy District" },
    new Supplier() { Name = "Charles", District = "Developers District" },
    new Supplier() { Name = "Hailee", District = "Scientists District" },
    new Supplier() { Name = "Taylor", District = "EarthIsFlat District" }
};

首先:

var suppliersAndBuyers = from s in suppliers
                         orderby s.District
                         join b in buyers on s.District equals b.District into buyersGroup
                         select buyersGroup.DefaultIfEmpty(
                             new Buyer()
                             {
                                 Name = string.Empty,
                                 District = s.District
                             });

foreach (var item in suppliersAndBuyers)
{
    foreach (var buyer in item)
    {
        Console.WriteLine($"{buyer.District} {buyer.Name}");
    }
}

第二种方法:

var suppliersAndBuyers = from s in suppliers
                                 orderby s.District
                                 join b in buyers on s.District equals b.District into buyersGroup
                                 from bG in buyersGroup.DefaultIfEmpty()
                                 select new
                                 {
                                     Name = bG.Name == null ? string.Empty : bG.Name,
                                     s.District,
                                 };

foreach (var item in suppliersAndBuyers)
{
    Console.WriteLine($"{item.District} {item.Name}");
}

两者都产生完全相同的输出,唯一的区别是我们输出结果的方式吗?我应该使用哪一个?

编辑:第一种方法返回 IEnumerable<IEnumerable<Buyer>>第二个返回 IEnumerable<AnonymousType> ,两者之间唯一有意义的区别在于它们返回的类型,这是两种方法之间唯一的决定因素,无论我想要一个类型还是匿名类型?

最佳答案

好的。据我所见:(A)

var suppliersAndBuyers = from s in suppliers
                         orderby s.District

枚举供应商列表。这很明显。现在,将其加入买家名单:

var suppliersAndBuyers = from s in suppliers
                         orderby s.District
                         join b in buyers on s.District equals b.District

这会创建匹配项(有些对象我不知道其类型,因为我面前没有正常的 Visual Studio 实例)。但例如,它就像 Harrison:Jonnie, Hailee:Peter, ... .现在我们可以基于这些匹配项(由变量 bs 表示)创建对象的 IEnumerable,如下所示:

var suppliersAndBuyers = from s in suppliers
                         orderby s.District
                         join b in buyers on s.District equals b.District
                         select new {
                             Supplier = s, Buyer = b
                         }

这将创建一个匿名类型的 IEnumerable,每个对象代表一对供应商和买方。

var suppliersAndBuyers = from s in suppliers
                         orderby s.District
                         join b in buyers on s.District equals b.District into buyersGroup

但是您决定做的是左连接,如标题中所写。它的作用是获取在片段 (A) 中创建的列表中的每个元素,并匹配一个 IEnumerable。买家列表中的所有匹配对象。这会产生可枚举的匹配项。例如,对于 Harrisonsuppliers 中的第一个条目列表,你会得到一个 IEnumerable包含 JohnnyPaulPiercesuppliers 中的其他元素相同列表,按他们的 District 排序.

这就是为什么你以 IEnumerable<IEnumerable<Buyer>> 结尾的原因.因为对于每个供应商(第一个 IEnumerable 维度),您都有一个 Buyer 的“列表” (二次元+类型解释)

然后合并空条目在我看来已经过时了,因为你不应该有 null s,但只是空的 IEnumerable s,然后在遍历它们时,您将不会碰到任何元素。 (虽然我不确定最后一段,因为我从来没有编译过代码所以我不知道)


现在至于合并部分,第一个示例创建了一个新的 Buyer每个条目的对象,然后取 DefaultIsEmpty .对于第二个示例,它首先创建第一维和第二维 FULL IEnumerables,然后在再次迭代时合并空值。正如我在评论中提到的,这是一个不需要的循环。

关于c# - Left Outer Join,这两种方法有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49017141/

相关文章:

c# - LINQ 序列化

mysql - mysql中自然连接和左连接在一起

MySQL 在 LEFT JOIN WHERE 中计数

c# - 在列值的时间序列中 - 如果行值为空,我如何使用以前的可用值。 c#(数据表/数据行)

c# - List.ForEach 在技术上是 LINQ 的一部分吗?

c# - 在 LINQ 中获取子实体满足某些条件的项目

c# - 如何在 aspx 页面中访问 linq 查询的属性?

c# - 如何在众多网站中共享通用功能?

c# - OpenTK.Graphics.OpenGL.GL 过时了吗?

mysql - 如何返回第一个表中的所有列,而仅返回第二个表中的 1 列