C# Linq复杂搜索导致NullReferenceException

C# Linq复杂搜索导致NullReferenceException,c#,linq-to-sql,telerik-open-access,C#,Linq To Sql,Telerik Open Access,我在统一搜索函数中使用了以下LINQ代码 var searchObjects = from objectA in this.context.DB.objectAs join objectB in this.context.DB.objectBs on objectA equals objectB.objectA into objectAB from AB in objectAB.Where(o => o.Type == "BasicGroup").DefaultIf

我在统一搜索函数中使用了以下LINQ代码

var searchObjects =
    from objectA in this.context.DB.objectAs
    join objectB in this.context.DB.objectBs on objectA equals objectB.objectA into objectAB
    from AB in objectAB.Where(o => o.Type == "BasicGroup").DefaultIfEmpty()
    select new { objectA, objectB = AB};

foreach (var searchWord in searchWords)
{
    var searchObjects =
        searchObjects.Where(p => p.objectA.Name.Contains(searchWord) ||
            (p.objectB != null &&
                (p.objectB.Name.Contains(searchWord) ||
                p.objectB.ID.contains(searchWord))));
}
目标是在objectA的名称字段或关联的objectB的名称或ID字段中查找搜索词。问题是,当我尝试枚举searchObjects时,它只返回一个NullReferenceException,没有进一步的细节

查询的第一部分返回正确的组合对象列表(没有任何过滤器),所以我认为问题不在于左连接

我无法找出导致异常的原因,因此,如果您有任何帮助,我们将不胜感激

我也在使用Telerik的OpenAccess ORM,但我不认为这会造成任何问题

编辑:

事实证明,这是Telerik OpenAccess ORM的一个问题,在某些情况下,它会放弃生成合理的SQL,将所有内容都提取到内存中,并将其视为L2对象(正如@Dead.Rabit所指出的,如果为空,则会失败)。似乎至少是问题的一部分的条件是.DefaultIfEmpty()前面的.Where(o=>o.Type==“BasicGroup”)。更新到最新版本的OpenAccess(我想是2013年第一季度的SPI)允许我将该条件重写为equals语句的一部分

on new { objectA.ID, Type = "BasicGroup" } equals new { ID = objectB.AID, Type = object.Type }

这在SP1之前是不可能的。通过这个新的查询,我能够将searchword Where子句组合到查询中,并且仍然让它生成SQL,而不是将其绘制到内存中。

我不是100%确定,但我认为您需要在匿名类型中使用
AB
而不是
objectB

select new { objectA, AB }

因为这是左连接的结果。

AB可以为null,因为您使用
DefaultIfEmpty()
函数创建它,但是如果
ObjectA.Name
也可以为null<第二条语句中的code>Contains()将抛出错误。类似地,如果ObjectB不为null时ObjectB.ID或ObjectB.Name可以为null,则您的
ObjectB!=null
guard子句不会产生预期效果

尝试对对象进行简单枚举,以确保问题与第一次查询有关

foreach( var item in searchObjects )
    Console.WriteLine( item.Type );
您重新定义searchObjects变量,我认为这是代码转储中丢失的东西,但值得一提的是JIC


最后,我不确定OpenAccess ORM,因为我从来没有使用过它,但是这个查询在LINQ的Dynamics CRM实现上会失败,它不支持where子句中的某些类型的条件(我不会详细介绍,因为它不相关,但在这个查询中,您已经破坏了所有条件:p)。浏览第三方LINQ实现中的gotcha文档绝对值得。

您应该将各个部分拆分,并在调试器中或通过转储方法检查每个部分的结果,以查看哪个位返回null。(我怀疑
DefaultIfEmpty()
当然可以返回null)@matthewatson,但我如何进一步拆分它呢?第一部分工作,它返回一个组合对象列表。第二部分有或条件,所以它们必须是同一where查询的一部分,不是吗?我知道是foreach中的部分破坏了查询,即使只进行了一次迭代。啊,我的代码就是这样写的,只是在问题中写错了。谢谢你指出这一点,但这并不能解决问题。嗯,看来你一针见血。异常是objectB名称或ID为null的结果。但是,我的早期版本的代码使用了.Any子查询而不是LINQ join,并且没有这个问题。是否有可能(可能是ORM)将这些数据绘制到对象中,然后将其作为LINQ2对象运行,从而导致空异常而不是在SQL中运行?这也解释了这个查询是如何从不区分大小写变为区分大小写的。有可能,我真的不能评论,但你是对的,如果查询是针对LINQ2对象执行的,它应该会失败。如果您感兴趣,您应该从SQL获取一个事务日志,以查看它在哪里拆分查询。就我个人而言,我只是通过实现一个不区分大小写、空安全的字符串比较函数来解决眼前的问题。实际解决方案被编辑成问题文本,但这为我指明了正确的方向。