Why does LINQ query throw an exception when I attempt to get a count of a type

≯℡__Kan透↙ 提交于 2019-12-06 17:33:23

问题


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                                                    
}; 

Can someone tell me why an exception is thrown when at the following line of code?

int count = dataCollection.Count();  

This is the exception:

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 ...

回答1:


The exception is thrown at the Count() statement because LINQ uses deferred execution and the actual LINQ query will not be executed until to call .Count(), .ToList(), etc.




回答2:


This looks like a normal null reference exception in linq2objects while it tries to execute your predicates or projections.

The cases were you'd get a null ref exception that I can think of are if some elements of the "somedata" collection are null, if "h.Year" is null (what type is that?), or if "p.somemoredate" is null..




回答3:


Deferred execution strikes again!

(First off, my first guess is that this is caused by p.somemoredate being null somewhere in your collection.)

Given your example, there's no way for us to really know, since you've simplified away the bits that are being queried. Taking it at its face, I would say that whatever "somedata" or "somemoredate" are the things you need to look at.

To figure this out, (when I get really desperate) I split the query into parts and watch where exceptions get thrown. Notice the .ToArray() calls which will basically "stop" deferred execution from happening temporarily:

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.

Broken up like this, it's a lot easier to see where the exception gets thrown, and where to look for problems.




回答4:


I ran into the same issue. It is annoying that MS did not provide built-in null detection and handling for the aggregate functions. The other issue is I wanted to ensure I got a 0 or $0 return result for nulls/empty query results, as I was working on dashboards/reporting. All of those tables would have data eventually, but early on you get a lot of null returns. After reading multiple postings on the subject I came up with this:

Retrieve the fields you want to return or later apply aggregate functions to first. Test for a null return. Return 0 if a null is detected.

If you do get actual data returned then you can safely utilize/apply the Count or Sum aggregate Linq functions.

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);
    }
}

Sum Example Below

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);
    }
}


来源:https://stackoverflow.com/questions/3666979/why-does-linq-query-throw-an-exception-when-i-attempt-to-get-a-count-of-a-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!