具有多个 LEFT JOIN 的 LINQ 查询

LINQ query with multiple LEFT JOIN

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

主要的table结构是这样的:

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

而订购 table 在主 table 中有字段名称,还有另一个数字字段作为订购编号,例如:

Color ColorOrder
Black 6
Blue 2
Cyan 3
Red 4

现在我想根据 Ordering Tables in LINQ 中的排序数字来排序 Main table。如果主table如果排序中没有相应的字段table那么排序编号应该是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]);

我的问题之一是订购 table 没有记录(国家/地区 Table)。所以当我连接到 table 时,无论我做什么,我都会得到

System.NullReferenceException: 'Object reference not set to an instance of an object.' cntord was null.

这是我的 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();

Enumerable.DefaultIfEmpty Method

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

Returns

IEnumerable An IEnumerable that contains defaultValue if source is empty; otherwise, source.

当列表为空时,

.DefaultIfEmpty() 将 return null


解决方案

因此,您需要在访问其属性之前null检查 LEFT JOIN table 的值。

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();