【问题标题】:LINQ query with multiple LEFT JOIN具有多个 LEFT JOIN 的 Linq 查询
【发布时间】:2021-11-08 09:35:22
【问题描述】:

我有 1 个主表和 3 个用于对主表中的字段进行排序的表。我将所有这些表作为列表返回。

主表结构是这样的:

Color Make Country
Black Mercedes Germany
Blue Mercedes Germany
Cyan Mercedes Germany
Red Mercedes Germany
Blue BMW Germany
Red BMW Germany
Blue Toyota Japan
Purple Mercedes Germany

Ordering 表在主表中有字段名称,另外一个数字字段作为它们的排序号,例如:

Color ColorOrder
Black 6
Blue 2
Cyan 3
Red 4

现在我想根据 Linq 中订购表中的订购号订购主表。如果在主表中,如果排序表中没有对应的字段,则排序号应为 0(例如在 ColorOrdering 中没有 Purple)

具体来说,我在 Access 和 Query 中制作了一个工作示例,如下所示:

SELECT Cars.Color, Cars.Make, Cars.Country,
IIf([MakeOrder] Is Null,0,[MakeOrder]) AS MkOrder,
IIf([ColorOrder] Is Null,0,[ColorOrder]) AS ClOrder,
IIf([CountryOrder] Is Null,0,[CountryOrder]) AS CntOrder
FROM ((Cars LEFT JOIN ColorOrder ON Cars.Color = ColorOrder.Color) 
LEFT JOIN MakeOrder ON Cars.Make = MakeOrder.Make) 
LEFT JOIN CountryOrder ON Cars.Country = CountryOrder.Country
ORDER BY 
IIf([MakeOrder] Is Null,0,[MakeOrder]),
IIf([ColorOrder] Is Null,0,[ColorOrder]), 
IIf([CountryOrder] Is Null,0,[CountryOrder]);

我的问题是订购表之一没有记录(国家表)。因此,当我加入该表时,无论我做什么,我都会不断得到,

System.NullReferenceException: '对象引用未设置为对象的实例。' cntord 为空。

这是我的 Linq 查询,非常感谢您的帮助

List<CarsWithOrdering> carsWithOrdering = (from c in Cars
//Also tried this, doesn't work
//join cntord in CountryOrderingList.DefaultIfEmpty()
// on c.Country equals cntord.Country
join cntord in CountryOrderingList
on c.Country equals cntord.Country into lcntord
from cntord in lcntord.DefaultIfEmpty()
//........ (Other 2 left joins similar to above one)
select new CarsWithOrdering
{
Color = c.Color,
Make = c.Make,
Country = c.Country,        
ColorOrder = int.Parse(colord.ItemValue) ?? 0,
MakeOrder = int.Parse(makord.ItemValue) ?? 0,
CountryOrder = int.Parse(cntord.ItemValue) ?? 0
}).ToList();

【问题讨论】:

  • 在访问其属性之前,您需要检查 LEFT JOIN 表是否为空。例如:cntord != null ? int.Parse(cntord.ItemValue) : 0。其他 LEFT JOIN 表也是如此。
  • 您好,谢谢,这解决了问题,如果您可以将其作为答案,我可以将其标记为答案,以便其他人也可以受益
  • 好吧,还有更多。如何将数据库中的结果放入 LINQ 查询中?如果这是通过一些像实体框架这样的 ORM,你应该完全摆脱这些连接并使用导航属性。
  • 嗨,没有那些列表是从 Excel 导入内存而不是从数据库中

标签: c# linq


【解决方案1】:

Enumerable.DefaultIfEmpty Method

public static System.Collections.Generic.IEnumerable<TSource> DefaultIfEmpty<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, TSource defaultValue);

返回

IEnumerable 如果源为空,则包含 defaultValue 的 IEnumerable;否则,来源。

.DefaultIfEmpty() 将在列表为空时返回null


解决方案

因此,您需要在访问其属性之前对 LEFT JOIN 表的值进行null 检查

List<CarsWithOrdering> carsWithOrdering = (from c in Cars
    join cntord in CountryOrderingList
    on c.Country equals cntord.Country into lcntord
    from cntord in lcntord.DefaultIfEmpty()
    //Other LEFT JOIN tables
    select new CarsWithOrdering
    {
        Color = c.Color,
        Make = c.Make,
        Country = c.Country,        
        ColorOrder = colord != null ? int.Parse(colord.ItemValue) : 0,
        MakeOrder = makord != null ? int.Parse(makord.ItemValue) : 0,
        CountryOrder = cntord != null ? int.Parse(cntord.ItemValue) : 0
    })
    .ToList();

【讨论】:

    猜你喜欢
    • 2017-04-07
    • 2021-01-28
    • 1970-01-01
    • 1970-01-01
    • 2019-04-25
    • 2015-07-14
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多