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

时间:2010-09-08 10:58:08

标签: c# linq exception-handling linq-to-objects

public readonly IEnumerable<string> 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                                                    
}; 

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

int count = dataCollection.Count();  

这是一个例外:

System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Linq.Enumerable.<SelectManyIterator>d__31`3.MoveNext()
   at System.Linq.Enumerable.<SelectManyIterator>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 ...

4 个答案:

答案 0 :(得分:10)

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

如果“somedata”集合的某些元素为null,如果“h.Year”为null(这是什么类型?),或者如果“p.somemoredate”为null ..

答案 1 :(得分:4)

延迟执行再次发生!

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

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

为了解决这个问题,(当我真的绝望时)我将查询分成几部分并观察异常被抛出的地方。注意.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.

像这样分解,可以更容易地看到异常被抛出的位置,以及在哪里寻找问题。

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

检索要返回的字段,或者稍后将聚合函数应用于该字段。 测试是否为空。如果检测到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);
    }
}