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

46,258

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

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

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

Solution 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);
    }
}
Share:
46,258
thenth
Author by

thenth

Updated on August 29, 2020

Comments

  • thenth
    thenth over 3 years
    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 ...
    
  • thenth
    thenth over 13 years
    Thank you. So this means that there is an actual error occurring in the Linq query itself?
  • Stefanvds
    Stefanvds over 13 years
    no it means that you didnt ask the count to an IEnuberable, you just forgot the .ToList()
  • Albin Sunnanbo
    Albin Sunnanbo over 13 years
    @Stefanvds: no it is very much OK to call the Count() method on the resulting IQueryable<T>/IEnumerable<T> without calling .ToList() first.
  • thenth
    thenth over 13 years
    Unfortunately, the exception is still thrown when I convert to a list?
  • Alex Humphrey
    Alex Humphrey over 13 years
    +1: Unless we get more information, this is the most likely cause. I meant to say someData rather than dataCollection in my comment on the question :).
  • Martin
    Martin about 13 years
    This is the correct answer ... funny, I already upvoted Albin's comment on the question a LONG time ago.
  • Ciccio
    Ciccio about 9 years
    The problem is that you have one of your property NULL, so when it tries to do a comparison the exception is thrown... the comparison is performed on Contains... but just when you do .Count() you really retrieve the result of the linq query..
  • eidylon
    eidylon about 2 years
    I don't think adding default null handling would really work, because in different situations you might want to treat nulls differently. Sometimes you might want to exclude them, other times you might want to NVL/IsNull them with a default value. The compiler can't know what your business logic needs to be.