1

I have an exception that is occurring, but I don't quite understand how it can be occurring. I would appreciate any tips on how to fix it, or advice on how I can better understand why the error is occurring.

Background Info

  • The error was logged to our error database, and I unfortunately haven't been able to reproduce the error myself.
  • This error occurred in a dashboard application that runs 24/7, and it attempts to refresh the data every minute. As such, this error has occurred multiple times in the last few weeks. While it's not exactly an urgent issue since the dashboard re-attempts to refresh data soon after, it bothers me that I haven't been able to fix it.

The error

This is the exception message that was logged: Object reference not set to an instance of an object. Looking it up, it seems like this is caused by a NullReferenceException. However, the Exception is occurring in Enumerable.ToDictionary(), which, according to the documentation, only throws an ArgumentNullException. Thus, I'm confused on which error is occurring, how, and why it is occurring.

Here is the relevant part of the stack trace.

   at PackerVM.<>c.<GetData>b__32_3(OrderDetail orderDetail) in PackerVM.cs:line 72
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector)
   at PackerVM.GetData() in PackerVM.cs:line 65

The code

Here is the code where the error is occurring.

_orderDetails = miiDb.OrderDetails  // OrderDetails is a DbSet<OrderDetail>
    .Where(orderDetail => orderDetail.Department == "MOLDING" && orderDetail.Location != null)
    .GroupBy(orderDetail => orderDetail.Location)
    .Select(orderDetails => orderDetails.OrderByDescending(w => w.ReleaseState)
        .ThenBy(orderDetail => orderDetail.Sequence)
        .ThenBy(orderDetail => orderDetail.PlannedStart)
        .FirstOrDefault())
    .ToDictionary(orderDetail => orderDetail.Location, orderDetail => new PackerPressData()
    {
        Location = orderDetail.Location,
        MachineStatus = orderDetail.MachineStatus,
        ReleaseState = orderDetail.ReleaseState,
        Tool = orderDetail.Tool,
        PartNumber = orderDetail.PartNumber
    });

Here is some additional details on the line numbers in the stack trace:

line 72 refers to this section of code: .ToDictionary(orderDetail => orderDetail.Location, orderDetail => new PackerPressData()

line 65 refers to this section of code: _orderDetails = miiDb.OrderDetails

My progress

The error is occurring in Enumerable.ToDictionary, so I started by looking up the Microsoft docs for Enumerable.ToDictionary, which is how I determined that the error is an ArgumentNullException. As mentioned before though, the message seems to correspond to a NullReferenceException, leading to my confusion.

This is basically where I'm stuck though as I haven't been able to reproduce the issue. As I mentioned, the data updates frequently, so my testing likely just hasn't ran for long enough to encounter it again.

I've tried manually adding checks when testing locally to see if any of the OrderDetails produced by the .Select() statement preceding the .ToDictionary() statement are null, but none were null.

The only thing I've been able to think of is to add a Where clause: .Where(orderDetail => orderDetail != null) between the .Select() and .ToDictionary() statements, but I'm not convinced that this would fix the root cause of the issue since I don't completely understand how an OrderDetail at that point can be null in the first place.

TLDR

Enumerable.ToDictionary() seems to be producing an ArgumentNullException, but the error message saved to our Error database corresponds to a NullReferenceException. Additionally, I don't understand how the objects used to produce the Dictionary object can be null at that point in the code.

James Z
  • 12,209
  • 10
  • 24
  • 44
Ethan
  • 51
  • 4
  • It has nothing to do with `ToDictionary`, that's for sure, since as you've said it will throw an `ArgumentNullException` not a `NullReferenceException` if the `source` is `null`. This is just where the query gets executed, so somewhere in the query before you access a property of an object that is `null`. – Tim Schmelter Jul 09 '21 at 20:26
  • 2
    SUGGESTION: 1) Write a small standalone test program. Copy/paste the LINQ query above. 2) Create some test data where `_orderDetails = miiDb.OrderDetails` returns one or more rows. I suspect ".ToDictionary()" will work fine. 3) Now create some different test data, which returns *NO* rows. 4) I suspect you'll reproduce your `Object reference not set to an instance of an object` error. In other words, what happens if you attempt ".ToDictionary()" on a null set? 5) If my hunch is correct, just split your LINQ into two expressions :) – paulsm4 Jul 09 '21 at 20:26
  • @paulsm4: all Linq methods above will throw an `ArgumentNullException` instead of a `NullReferenceException` if the source sequence was `null`. Apart from that the `DbSet` is only null if it was declared as field or non public, which seems not to be the case since OP said it's was almost always working. If there are now rows, the dictionary should be empty. – Tim Schmelter Jul 09 '21 at 20:38
  • 1
    I guess there was a null entity, for whatever reason, maybe added from somewhere – Tim Schmelter Jul 09 '21 at 20:45
  • What happens if you replace `FirstOrDefault` by `First`. Do the exception type and message change? FirstOrDefault has the potential to return a null reference (though I would think all groups have at least one element so it should not return null...) – lidqy Jul 09 '21 at 20:46
  • @lidqy: doesn't make a difference since there is no predicate and all groups have at least one element, otherwise there was no group. It's just confusing to use `FirstOrDefault` – Tim Schmelter Jul 09 '21 at 20:48
  • @TimSchmelter Thats a good idea (the added null entity) the code looks as if orderDetail can never be null. But the magic of Linq being translated to SQL and other DB operation under way in the background might cause this... – lidqy Jul 09 '21 at 20:49
  • @TimSchmelter yes you are right that all groups have at least one item and so First vs FirstOrDefault *shouldn't* make any diff. But at the same time it seems odd that there is a null ref at all, because also the orderDetail arg in the lambdas should never be null... So somewhere there is a null ref... – lidqy Jul 09 '21 at 20:52
  • My last comment: I assume it has something to do with entity mapping and cite: "*it attempts to refresh the data every minute*". Some entity is nuked to null by the refreshing routine. – lidqy Jul 09 '21 at 20:54
  • Does this answer your question? [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – derpirscher Jul 09 '21 at 21:15
  • Can you please add SQL generated by the EF? – Guru Stron Jul 09 '21 at 22:14

0 Answers0