为什么我没有收到Null引用异常?

Sud*_*002 3 c# linq linq-to-entities

我正在使用LINQ to Entities从数据库中获取一些数据。以下是我的查询。

var location = from l in dbContext.Locations
join e in dbContext.Equipment on l.ID equals e.LocationID into rs1
from e in rs1.DefaultIfEmpty()
where ids.Contains(l.ID)
select new
{
    EquipmentClass = e,
    LocationID = l.ID,
    LocationName = l.Name,
    EquipmentName = e == null ? null : e.Name,
    Description = e == null ? null : e.Description,
    InServiceStatus = e == null ? false : e.InServiceStatus,
    EquipmentType = e.EquipmentType.Name
};

foreach (var item in location)
{
    // some logic
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,ids是我传递以过滤结果的int列表。当得到结果时,我看到返回记录之一为null EquipmentClass。我执行了一些空检查,但意识到我忘记对其中一个属性进行空检查。现在,我希望得到一个空引用异常,EquipmentType = e.EquipmentType.Name但我没有。令我惊讶的是,它工作得很好,并且设置为null。My EquipmentClass的属性类型为EquipmentType,是另一类。EquipmentType具有Name一个字符串属性。

  1. 为什么这不会引发空引用异常?

就像一个测试一样,我从中删除了空检查,InServiceStatus = e == null ? false : e.InServiceStatus并且在使用查询运行foreach循环时,它以无效的操作异常失败。

  1. 这是否意味着我只需要对不可为空的值进行空检查?

更新

foreach (var item in location)
{
    var p = item.EquipmentClass.EquipmentType.Name;
}
Run Code Online (Sandbox Code Playgroud)

在查询后立即添加此内容。关于p的赋值,我得到一个空引用异常。我不确定它到底能走多远,因为它应该在foreach循环的第一行失败。没有声明变量p的行,我不会得到null引用异常。如果有人能解释发生了什么,我将不胜感激。仅供参考,在foreach循环开始时,item.EquipmentClass和的值item.EquipmentType都为空。

Update2: 我发现此链接在哪里似乎有人使用LINQ to SQL几乎存在相同的问题。我得到了答案的要点,但并不完全理解它对上面两个问题的潜在影响。

Geo*_*org 5

如果你写对LINQ查询IQueryable,什么情况是,这些方法,你是在幕后调用(如SelectWhere等)没有做任何事情不仅仅是记录你怎么称呼他们,也就是说,它们记录了谓词表达式并继承LINQ提供程序。一旦开始迭代查询,就会要求提供程序执行查询模型。因此,基本上,提供程序使用表达式模型为您提供预期类型的​​结果。

完全不需要编译器实际编译甚至执行您作为表达式提供的代码(模型)。实际上,LINQ to SQL或LINQ to Entities的全部要点是提供程序不执行此操作,而是将代码表达式转换为SQL。

因此,您的查询实际上呈现为SQL查询,并且该查询的结果被转换回。因此,e您在查询中看到的变量不一定是真正创建的,而是仅用于LINQ提供程序来编译SQL查询。但是,大多数数据库服务器的传播为空。

针对LINQ to Objects运行相同的查询,您将得到缺少的NullReferenceException