2010-03-23 66 views
14

下面的代码工作,除非p.School.SchoolName原来是空,在这种情况下,它会导致一个NullReferenceException。LINQ where子句和计数结果无效例外

if (ExistingUsers.Where(p => p.StudentID == item.StaffID && 
         p.School.SchoolName == item.SchoolID).Count() > 0) 
{ 
    // Do stuff. 
} 

ExistingUsers是用户的列表:

public List<User> ExistingUsers; 

这里是堆栈跟踪的相关部分:

System.NullReferenceException:未设置为一个对象的实例对象引用。

在System.Linq.Enumerable.WhereListIterator 1.MoveNext()
at System.Linq.Enumerable.Count[TSource](IEnumerable
1源)

我应该如何处理这个where子句?

非常感谢。

+5

你确定它的SchoolName是零,而不是p.School? – 2010-03-23 04:13:22

+6

作为一般说明,而不是IEnumerable.Count(谓词)> 0,使用IEnumerable.Any(谓词)。这将终止第一场比赛的执行,可能会产生很大的加速。 – recursive 2010-03-23 04:16:48

+0

@Anthony:非常感谢,我认为你是正确的p.School是空的。 – IntrepidDude 2010-03-23 04:35:02

回答

24

我怀疑p.School为空,而不是SchoolName。只需在访问SchoolName之前添加空检查。另外,使用Any()检查是否有任何结果,而不是Count() > 0,除非您真的需要计数。由于并不是所有的项目都存在迭代,所以性能更好。

var result = ExistingUsers.Where(p => p.StudentID == item.StaffID 
          && p.School != null 
          && p.School.SchoolName == item.SchoolID) 
         .Any(); 

if (result) { /* do something */ } 
+0

这工作就像一个魅力。非常感谢,我学到了! – IntrepidDude 2010-03-23 04:44:11

0

如果您想要得到空值(所有学生,与学校或没有)使用左连接。

有MSDN上

0

如果我没有记错的一个很好的例子(没有在此刻我的开发PC,可以与反射器不检查)中调用instance implementationstring.Equals(string),使用==操作的结果,而不是静态实现String.Equals(string, string)

假设你的问题是由于SchoolName被空,正如你提到的,试试这个:

if (ExistingUsers.Where(
    p => p.StudentID == item.StaffID 
    && String.Equals(p.School.SchoolName, item.SchoolID)).Count() > 0) 
{ 
    // Do stuff. 
} 

当然,通过其他的答案评论数以及:

  • 使用Any()代替Count() > 0通常会表现更好
  • 如果p.School为空,则需要额外支票

希望这有助于。

1

对于所有数据库可为空的列,我们应该添加空值检查或做简单的比较a == b而不是a.ToLower() == b.ToLower()或类似的字符串操作。
我的观察如下:
当他们打通LINQ查询的可枚举迭代的比较对与输入的字符串/值时,任何空值(数据库列)和操作也将引发异常,但可枚举变得NULL,虽然查询不为null。