16
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 ...
DaveDev
  • 38,095
  • 68
  • 199
  • 359
thenth
  • 481
  • 2
  • 5
  • 8
  • What's the exact exception? You've only posted a stack trace... – Bertvan Sep 08 '10 at 11:00
  • I have added in the full exception. – thenth Sep 08 '10 at 11:23
  • 1
    Due to the lazy evaluation-ness of LINQ, and looking at that stack trace, I'd guess that your error is in the code which creates `dataCollection`. Try `var x = dataCollection.ToList();` before you do the count - if it throws the same error, then the problem's not in the code you posted. (I'm assuming `dataCollection` is an IEnumerable). – Alex Humphrey Sep 08 '10 at 11:25
  • 3
    The most likely cause of the exception is that p.somemoredate is null for some p. Inspect "somedata" for any item with somemoredate == null. – Albin Sunnanbo Sep 08 '10 at 11:35
  • Sorry I meant `someData.ToList()` and that `someData` is an IEnumerable. – Alex Humphrey Sep 08 '10 at 11:36

4 Answers4

14

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

Diego Veralli
  • 763
  • 4
  • 12
  • This is the correct answer ... funny, I already upvoted Albin's comment on the question a LONG time ago. – Martin Mar 24 '11 at 13:08
4

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.

Dave Markle
  • 88,065
  • 20
  • 140
  • 165
  • +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 :). – Alex Humphrey Sep 08 '10 at 11:37
2

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.

Albin Sunnanbo
  • 44,354
  • 8
  • 64
  • 104
  • Thank you. So this means that there is an actual error occurring in the Linq query itself? – thenth Sep 08 '10 at 11:03
  • no it means that you didnt ask the count to an IEnuberable, you just forgot the .ToList() – Stefanvds Sep 08 '10 at 11:05
  • 11
    @Stefanvds: no it is very much OK to call the Count() method on the resulting IQueryable/IEnumerable without calling .ToList() first. – Albin Sunnanbo Sep 08 '10 at 11:13
  • 1
    Unfortunately, the exception is still thrown when I convert to a list? – thenth Sep 08 '10 at 11:16
  • 3
    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.. – Ciccio Feb 19 '15 at 11:32
1

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);
    }
}
JHobern
  • 858
  • 1
  • 12
  • 19
Les Baker
  • 11
  • 2