当我尝试获取类型的计数时,为什么LINQ查询会抛出exception

public readonly IEnumerable PeriodToSelect = new string[] { "MONTH" }; var dataCollection = from p in somedata from h in p.somemoredate where h.Year > (DateTime.Now.Year - 2) where PeriodToSelect.Contains(h.TimePeriod) select new { p.Currency, h.Year.Month, h.Value }; 

有人可以告诉我为什么在下面的代码行中抛出exception?

 int count = dataCollection.Count(); 

这是例外:

 System.NullReferenceException: Object reference not set to an instance of an object. at System.Linq.Enumerable.d__31`3.MoveNext() at System.Linq.Enumerable.d__31`3.MoveNext() at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) at ... 

在Count()语句中抛出exception,因为LINQ使用延迟执行,并且在调用.Count() .ToList()等之前不会执行实际的LINQ查询。

当它尝试执行谓词或预测时,这看起来像linq2objects中的普通空引用exception。

如果“somedata”集合的某些元素为null,如果“h.Year”为null(这是什么类型?),或者如果“p。”,那么你会得到一个空引用exception。 somemoredate“是null ..

延期执行再次发生!

(首先,我的第一个猜测是,这是由于p.somemoredate在您的集合中某处为空而引起的。)

举个例子,我们无法真正知道,因为你已经简化了被查询的位。 从表面上看,我会说无论“somedata”还是“somemoredate”都是你需要关注的东西。

为了解决这个问题,(当我真的很绝望时)我将查询分成几部分并观察exception被抛出的地方。 注意.ToArray()调用基本上会“停止”延迟执行暂时发生:

 var sd = somedata.ToArray(); var x = (from p in sd from h in p.somemoredate.ToArray()).ToArray(); //My guess is that you'll get your exception here. 

像这样分解,更容易看到exception被抛出的地方,以及在哪里寻找问题。

我遇到了同样的问题。 令人讨厌的是MS没有为聚合函数提供内置的空值检测和处理。 另一个问题是我想确保我在null / /查询结果中得到0或$ 0返回结果,因为我正在处理仪表板/报告。 所有这些表最终都会有数据,但是在早期您获得了大量的null返回。 在阅读了关于这个主题的多个post后,我想出了这个:

检索要返回的字段,或稍后将聚合函数应用于第一个。 测试空值返回。 如果检测到null,则返回0。

如果确实获得了实际数据,则可以安全地使用/应用Count或Sum聚合Linq函数。

 public ActionResult YourTestMethod() { var linqResults = (from e in db.YourTable select e.FieldYouWantToCount); if (linqResults != null) { return Json(linqResults.ToList().Count(), JsonRequestBehavior.AllowGet); } else { return Json(0, JsonRequestBehavior.AllowGet); } } 

下面的总和示例

 public ActionResult YourTestMethod() { var linqResults = (from e in db.YourTable select e.Total); if (linqResults != null) { return Json(linqResults.ToList().Sum(), JsonRequestBehavior.AllowGet); } else { return Json(0, JsonRequestBehavior.AllowGet); } }