C# Linq复杂搜索导致NullReferenceException
我在统一搜索函数中使用了以下LINQ代码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
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获取一个事务日志,以查看它在哪里拆分查询。就我个人而言,我只是通过实现一个不区分大小写、空安全的字符串比较函数来解决眼前的问题。实际解决方案被编辑成问题文本,但这为我指明了正确的方向。