سؤال

Under the debugger I have a case where DbContext.ChangeTracker.Entry(e) returns an entry with a State of Detached. When I enumerate the results of DbContext.ChangeTracker.Entries() and the entries of the underlying ObjectContext when looking for e, I find an entry with a State of Unchanged (expected).

What is going on?

Here are some additional details:

  • using POCO entities.
  • change Tracking is on
  • proxy creation is off
  • lazy loading is off
  • problem does not occur when saving an entity for the first time (e.g. adding to context); occurs when getting old entity into context then trying to make changes to it. This is an aggregate root with many "reference" entities that aren't supposed to change
  • Equals is overridden on the entities and IEquatable<T> is implemented. That code is generated by T4.
  • I am using a generic repository implementation that is declaratively configured to generate rules for saving (e.g. whether entities should be added, attached/modified, attached/unchanged. It seems to be doing this in the right order. For example the aggregate root is added/attached last because attaching it first brings in other entities in a modified state (adding those first as unchanged prevents this).
هل كانت مفيدة؟

المحلول

(Answered in a question edit. Converted to a community wiki answer. See Question with no answers, but issue solved in the comments (or extended in chat) )

The OP wrote:

I have "solved" the problem, but I still want to know what's going on, because my solution doesn't do anything to address the root cause. My "solution" looks for an entity in the change tracker (I have also looked via the context.Entry() and context.Set().Local -- when I do it with this code (I did it as a loop instead of LINQ so I could set breakpoints), it works:

private DbEntityEntry GetChangeTrackedEntry(IEntity mine, Type type)
    {
        foreach (var en in context.ChangeTracker.Entries())
        {
            if (en.Entity.GetType() != type)
                continue;
            if (((IEntity)en.Entity).Id != mine.Id)
                continue;
            return en;
        }

        return null;
    }

When I attempt to lookup an entity (via change tracker, the set, etc.) via using mine directly, that's when I end up with a detached case.

I thought perhaps there were cases of EF using ReferenceEquals but @Ladislav's comment may indicate something wrong with Equals implementation.

If anyone has a further explanation they can edit that into this community wiki answer.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top