1

We occasionally see this exception in our logs, but can't figure out how to reproduce it under test:

System.NullReferenceException: Object reference not set to an instance of an object.
at System.Data.Objects.EntityEntry.DetectChangesInProperty(Int32 ordinal, Boolean detectOnlyComplexProperties, Boolean detectOnly)
at System.Data.Objects.EntityEntry.DetectChangesInProperties(Boolean detectOnlyComplexProperties)
at System.Data.Objects.ObjectStateManager.DetectChangesInScalarAndComplexProperties(IList1 entries)
at System.Data.Objects.ObjectStateManager.DetectChanges()
at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean force)
at System.Data.Entity.Internal.Linq.InternalSet
1.Find(Object[] keyValues)
at

The failing method System.Data.Objects.EntityEntry.DetectChangesInProperty(Int32 ordinal, Boolean detectOnlyComplexProperties, Boolean detectOnly) decompiles with dotPeek (plus my comments) to:

private bool DetectChangesInProperty(
  int ordinal,
  bool detectOnlyComplexProperties,
  bool detectOnly)
{
  bool changeDetected = false;
  // possible System.NullReferenceException on _cacheTypeMetadata
  StateManagerMemberMetadata managerMemberMetadata = this._cacheTypeMetadata.Member(ordinal);
  // possible System.NullReferenceException on managerMemberMetadata (if a null entry exists in _members[])
  object obj1 = managerMemberMetadata.GetValue(this._wrappedEntity.Entity);
  if (managerMemberMetadata.IsComplex)
  {
    if (this.State != EntityState.Deleted)
    {
      object complexObjectSnapshot = this.GetComplexObjectSnapshot(this.Entity, ordinal);
      if (this.DetectChangesInComplexType(managerMemberMetadata, managerMemberMetadata, obj1, complexObjectSnapshot, ref changeDetected, detectOnly))
      {
        this.CheckForDuplicateComplexObjects(obj1);
        if (!detectOnly)
        {
          ((IEntityChangeTracker) this).EntityMemberChanging(managerMemberMetadata.CLayerName);
          // possible System.NullReferenceException on _cache
          this._cache.ChangingOldValue = complexObjectSnapshot;
          ((IEntityChangeTracker) this).EntityMemberChanged(managerMemberMetadata.CLayerName);
        }
        this.UpdateComplexObjectSnapshot(managerMemberMetadata, this.Entity, ordinal, obj1);
        if (!changeDetected)
          this.DetectChangesInComplexType(managerMemberMetadata, managerMemberMetadata, obj1, complexObjectSnapshot, ref changeDetected, detectOnly);
      }
    }
  }
  else if (!detectOnlyComplexProperties)
  {
    object obj2;
    // possible System.NullReferenceException on _wrappedEntity
    this.FindOriginalValue(managerMemberMetadata, this._wrappedEntity.Entity, out obj2);
    object originalValue = ((StateManagerValue) obj2).originalValue;
    // possible System.NullReferenceException on object
    if (!object.Equals(obj1, originalValue))
    {
      changeDetected = true;
      if (managerMemberMetadata.IsPartOfKey)
      {
        // static so no possible System.NullReferenceException
        if (!ByValueEqualityComparer.Default.Equals(obj1, originalValue))
          throw EntityUtil.CannotModifyKeyProperty(managerMemberMetadata.CLayerName);
      }
      else if (this.State != EntityState.Deleted && !detectOnly)
      {
        ((IEntityChangeTracker) this).EntityMemberChanging(managerMemberMetadata.CLayerName);
        ((IEntityChangeTracker) this).EntityMemberChanged(managerMemberMetadata.CLayerName);
      }
    }
  }
  return changeDetected;
}

There are several places where a NullReferenceException could be thrown, and I can't begin to guess. If we knew how to reliably reproduce the problem I could step through, but I don't. So far, this is all I have.

We have a large ASP.NET website solution with dozens of repositories which all use the same type of DbContext. We haven't implemented instance-per-request yet, but we know we have to. It'll take us several weeks to do it. We think this is the cause of the exception. In the meantime we have various approaches to newing up DbContext: per method call (expensive), now being replaced by (less expensive but also-smelly) service locators, with a bit of Autofac (still not instance per request because of that being incompatible with our version of MVC plus async).

We want to figure out how to reproduce this error reliably, so that we can know that instance-per-request has actually fixed the problem. So the underlying question is not "how do we fix this", but "how do we reproduce it"? And to answer that, I'm curious as to how this exception is actually happening.

OutstandingBill
  • 2,614
  • 26
  • 38
  • 2
    You problem seems to be you cant guess as to where it would be thrown, but you are expecting us to guess. This is case for logging, or debugging – TheGeneral Mar 04 '19 at 03:24
  • _We haven't implemented instance-per-request yet_ - how you are using DbContext now? – Fabio Mar 04 '19 at 03:58
  • @Michael, I'm not expecting anyone to guess, no, merely asking the question in the hope someone can provide some insight. Such as perhaps "I had this exception when..." or "try MagicProblemSolver (tm)". I admit it's a long shot, but since I'm stuck and I've exhausted all the avenues I can think of... – OutstandingBill Mar 04 '19 at 08:20
  • Its simple really, log every line until you find the one with the exception, line1, line2, line3.. or turn on line numbers, attach to a debugger and test. there isnt a problem you cant log or debug – TheGeneral Mar 04 '19 at 08:22
  • @Michael, yes, logging every line would be a good strategy if this were my own code. It's `System.Data` code though. – OutstandingBill Mar 04 '19 at 08:30
  • @Fabio, I edited my question to answer your question – OutstandingBill Mar 04 '19 at 08:32
  • @Michael, I noticed that the part of the question which said where the code snippet came from (i.e. dotnPeek) had become obscured. Apologies. Fixed now – OutstandingBill Mar 04 '19 at 08:38
  • 1
    instantiating new instance of DbContext for every query is not expensive, at least in web application, DbContext is just an object. But it depends on how you are using DbContext. You mentioned service locator and Autofac, not sure, but would investigate what you do differently with DbContext there. If you 100% sure this is EF problem post issue on their github. – Fabio Mar 04 '19 at 09:00

0 Answers0