-1

We're getting an inconsistent null reference exception while assigning a non-nullable scalar variable to an Entity Framework domain object property. I understand what a null reference exception is, but I can't understand how you would get one when assigning a non-null value to a property of a non-null EF domain object.

The domain object looks like this:

[DataContract]
[Table("Participant", Schema = "tour")]
public partial class Participant
{
    public Participant()
    {
    }
    [DataMember]
    [Key]
    public int ParticipantID { get; set; }
    ...
    public DateTime? AutopayLastAttemptedUtc { get; set; }
}

The area where we are getting the exception is:

DateTime utcNow = DateTime.UtcNow;
// The below line throws the Null Reference Exception.
participant.AutopayLastAttemptedUtc = utcNow;
ParticipantService.Update(participant);

I still get an exception on the same line if I add some debug code to prove variables are not null:

DateTime utcNow = DateTime.UtcNow;
// This line proves that participant is not null and that
// AutopayLastUpdatedUtc can be read (not that that really
// matters because we only want to set it
TelemetryClient.TrackTrace("Participant", SeverityLevel.Information, new Dictionary<string, string> {
    { "ParticipantId", participant.ParticipantID.ToString() },
    { "AutopayLastUpdatedUtc", participant.AutopayLastAttemptedUtc.ToString() }
});
// The below line throws the Null Reference Exception.
participant.AutopayLastAttemptedUtc = utcNow;
ParticipantService.Update(participant);

I don't understand what could possibly be null

  • participant can't be null because we use it in the debug code on the line above
  • utcNow can't be null because it's a non-nullable type
  • AutopayLastUpdatedUtc is a standard EF setter

Note that I am not asking what a null reference exception is. I am asking how a null reference exception could possibly happen when assigning a non-null value to a property of a non-null object.

thelem
  • 2,642
  • 1
  • 24
  • 34
  • AutopayLastUpdatedUtc is null-able and if it happens to be null, the .ToString() will throw the exception. Also, you need to check if the instance for participant is not null. – Sparrow Oct 16 '17 at 17:08
  • 2
    If you see the exception in a **release** build then line numbers reported may be wrong. E.g., the specific statement throwing the exception may not be the one you think it is. – Martin Liversage Oct 16 '17 at 17:09
  • There is only one nullable variable here... it's not rocket science. I bet if you check, AutopayLastAttemptedUtc is null when this happens. – Erik Funkenbusch Oct 16 '17 at 17:09
  • @Sparrow that is not the line that is throwing the exception, I included that as debug to show that neither participant nor AutopayLastUpdatedUtc were null. Not that it should matter if AutopayLastUpdatedUtc were null because it is the setter line that is throwing the exception. – thelem Oct 16 '17 at 20:55
  • @Martin Liversage good point but I'm confident the line numbers are correct because this is a debug build and I keep adding/removing debug code but the line with the error is consistent – thelem Oct 16 '17 at 20:58
  • @Erik Funkenbusch that shouldn't matter because it is a setter that is throwing the exception – thelem Oct 16 '17 at 21:00
  • Does it still throw if you comment out the `TelemetryClient.TrackTrace` call? – mxmissile Oct 16 '17 at 21:22
  • @mxmissile Yes. – thelem Oct 16 '17 at 21:34
  • If you get the exception in a debug build you should try to use the debugger to understand what reference is null. You can configure the debugger to break when a `NullReferenceException` is thrown in the Exception debug window. If for some reason it is hard to use the debugger you can instrument your code. Just log everything starting with `participant` and then every property on `participant` that can be null. – Martin Liversage Oct 17 '17 at 04:39
  • @MartinLiversage "Just log everything starting with participant" - isn't that exactly what the question already shows with `TelemetryClient.TrackTrace`? – IMSoP Oct 17 '17 at 10:03
  • @IMSoP: The information provided in this question seems to indicate that there is something really weird going on where a reference that cannot be null is null. However, computers don't work that way. They are quite predictable and the analysis of the problem must be wrong (there is a null reference somewhere in the code and Schrödinger's Cat is not involved). I'm just giving some advice on how to find that reference. I predict that this question soon can be closed as _a problem that can no longer be reproduced_. – Martin Liversage Oct 17 '17 at 11:14
  • @MartinLiversage Sure, but your advice seemed to be "debug the things you've already shown us that you're debugging". Perhaps you could give the OP some examples of things that they *haven't* shown us they've debugged that you think might be relevant to the problem; "log everything" is pretty vague advice. – IMSoP Oct 17 '17 at 11:17
  • @IMSoP: I specifically said log `participant` and every property on `participant`. I think that it is quite specific. However, there is something wrong in the question. We are told that a `NullReferenceException` is thrown in a specific line and the only reference in that line is `participant`. On the other hand we are also told that this reference cannot be `null`. This is a contradiction so there must be something more going on which we don't know about because it is not included in the question, hence my more vague suggestion to "log everything" including the stuff that was omitted. – Martin Liversage Oct 17 '17 at 11:29

1 Answers1

0

Despite having checked this several different ways already, @MartinLiversage was correct that the reported line numbers were off. The exception was actually being thrown by a later line (not shown in the sample code) and was easy to fix once I found the line with the problem.

My test case for reproducing this was on our test server rather than my development machine. That's fairly normal, because the databases are different and it's not always easy to find a database record that triggers the same problem on my development database. It does make debugging harder though. The test server builds with "Define DEBUG constant" set, but it does also have "Optimize code" set, so I wonder if that is what is causing the lines to be incorrectly reported.

thelem
  • 2,642
  • 1
  • 24
  • 34
  • Yes, that's exactly what causes the issue.. and why it was asked several times if you were using a release build. Release (even if you have DEBUG preprocessor set) is optimized, and distorts the debugging information. – Erik Funkenbusch Oct 19 '17 at 18:46
  • @ErikFunkenbusch I only see one comment suggesting this was the problem, which is the one I've upvoted and mentioned in my answer. Even that just used the term "release build", which I understood to mean the DEBUG constant was not defined (release being the opposite of debug). I have a configuration called "Release", but it's not the one that was in use. If it's the "Optimize code" option that causes the line numbers problem then the ideal answer should mention that option, rather than "Release" which can have multiple definitions. – thelem Oct 20 '17 at 10:42