Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EF Core instance of entity type cannot be tracked #10

Closed
robertlarkins opened this issue May 11, 2021 · 6 comments
Closed

EF Core instance of entity type cannot be tracked #10

robertlarkins opened this issue May 11, 2021 · 6 comments

Comments

@robertlarkins
Copy link

I've been following the approaches proposed in this repo and the associated pluralsight course, and they have worked really well, but recently been getting the following exception thrown by EFCore:

"The instance of entity type 'YourEntity' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked.
When attaching existing entities, ensure that only one entity instance with a given key value is attached.
Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values."

I have created a minimum example to demonstrate the issue (using EFCore inmemory and a Sqlite DB) here: https://github.com/robertlarkins/efcore-cannot-track-entity-issue

As far as I can determine it is related to static entities (such as Course in this repo, or Appointment Status in my linked repo), and it occurs when the context is holding an instance of AppointmentStatus pulled from the database, and the same AppointmentStatus is added to the context from the static AppointmentStatus reference in code. When trying to save the context to the database the above exception gets thrown.

This exception occurs on this line:

IEnumerable<EntityEntry> enumerationEntries = ChangeTracker.Entries()
                .Where(x => EnumerationTypes.Contains(x.Entity.GetType()));

so it never gets to the point of trying to set the EntityState as unchanged.

Is this an issue you have come across before? I couldn't find how this repo stops this occurring, hopefully I have just missed something, but if not, then I assume it could potentially happen within this repo as well. Alternatively should this issue be presented on the EFCore issue tracker?

@robertlarkins
Copy link
Author

As a side note, this issue can be avoided by getting the desired AppointmentStatus instance from the db directly rather than from the static entity value, but this defeats the purpose of having static values, and requires additional calls to the db.

@robertlarkins
Copy link
Author

robertlarkins commented May 11, 2021

I finally found EFCore issues that (appear to) relate to this issue:
dotnet/efcore#23615 (comment)
dotnet/efcore#20124 (currently open)
dotnet/efcore#20116 (comment)
dotnet/efcore#19984 (comment)
dotnet/efcore#19877
dotnet/efcore#11457 (currently open)

@vkhorikov What is your thoughts on the best way of resolving this issue when using entities with static values (immutable entities)? Is there anything that could be added to the Entity class (in CSharpFunctionalExtensions) to assist with this?

I have also found the following, but unsure if they will help for the above situation:

@vkhorikov
Copy link
Owner

Not sure why this is not working. Try adding lazy loading to your reference project, maybe that's the difference here.

It's impossible to make changes in CSharpFunctionalExtensions to avoid this issue, it is core to how EF keeps track of entities in its DbContext. As usual, it's unnecessarily overcomplicated; it's a solved problem in NHibernate.

@robertlarkins
Copy link
Author

robertlarkins commented May 14, 2021

In our main project we have lazy loading, and this issue is occurring 😢. I couldn't figure out if or how to add lazy loading to the example solution, I suspect that the InMemoryDB doesn't cater for it.

From reading and my (limited) understanding what is happening is some query pulls the static defined variable into the context (say AppointmentStatus.Finished in this case), such as when getting all the Appointments, so this become the instance known to the context, but when updating an appointment to AppointmentStatus.Finished from the static code, this becomes a second instance tracked by the context. EF then sees these as two separate instances for the same thing (even though they are the same, and immutable), as EF determines equivalency by reference equals.

You're right, because of how EF tracks entities (using reference equals) nothing on the Entity class will help. At this stage I guess we continue with pulling the values from the db when necessary until EF better handles this (whenever that might be).

I'll go and create this as an EFCore issue and see what is said. Thanks again for your response @vkhorikov.

@pantonis
Copy link

@robertlarkins I have the same issue in latest EF Core. What is the solution to this? How can this be fixed? Thank you

@pantonis
Copy link

FYI I opened a ticket for this here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants