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

[Question] Type entities managed by Application #17661

Closed
bopazyn opened this issue Sep 6, 2019 · 2 comments
Closed

[Question] Type entities managed by Application #17661

bopazyn opened this issue Sep 6, 2019 · 2 comments
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported

Comments

@bopazyn
Copy link

bopazyn commented Sep 6, 2019

The class ExpenseType contains static readonly objects that represents all possible types. The domain logic depends on them and shouldn't know about DbContext. All of ExpenseTypes are stored in database using HasData. Before saving i ensure that all entites of type ExpenseType have Unchanged state.

Both ExpenseType and Expense have overridden Equals, GetHashCode methods but implementation of StateManager's private dictionaries compare references.

Is there another way to overcome this problem.

Exception message: 
    The instance of entity type 'ExpenseType' 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.
Stack Trace:
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.ThrowIdentityConflict(InternalEntityEntry entry)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry, Boolean updateDuplicate)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Nullable`1 forceStateWhenUnknownKey)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode node, Boolean force)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode node, TState state, Func`3 handleNode)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState entityState, Boolean forceStateWhenUnknownKey)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NavigationFixer.NavigationReferenceChanged(InternalEntityEntry entry, INavigation navigation, Object oldValue, Object newValue)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntryNotifier.NavigationReferenceChanged(InternalEntityEntry entry, INavigation navigation, Object oldValue, Object newValue)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.DetectNavigationChange(InternalEntityEntry entry, INavigation navigation)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.DetectChanges(InternalEntityEntry entry)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.DetectChanges(IStateManager stateManager)
    at Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.DetectChanges()
    at Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.Entries[TEntity]()
    at EfCoreProblemWithDDD.ExampleDbContext.SaveChanges(Boolean acceptAllChangesOnSuccess) in C:\Workspace\_experiments\EfCoreProblemWithDDD\src\EfCoreProblemWithDDD\ExampleDbContext.cs:line 18
    at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
    at EfCoreProblemWithDDD.Tests.Tests.Test1() in C:\Workspace\_experiments\EfCoreProblemWithDDD\test\EfCoreProblemWithDDD.Tests\Tests.cs:line 40

Steps to reproduce

I have created repo that contains minimal working example showing my problem:
https://github.com/bopazyn/EfCoreProblemWithDDD

Further technical details

EF Core version: 2.2.0
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Windows 10
IDE: Visual Studio Professional 2017 15.9.15

@AndriySvyryd
Copy link
Member

AndriySvyryd commented Sep 6, 2019

@bopazyn Thanks for the repro project.
The best way of doing this would be by using value objects.

But for now you can just attach all the known instances before performing any query:

dbContext.Attach(ExpenseType.Bills);
dbContext.Attach(ExpenseType.Food);
dbContext.Attach(ExpenseType.Hobby);

This also removes the need to mark them as unchanged before SaveChanges.

@AndriySvyryd AndriySvyryd added the closed-no-further-action The issue is closed and no further action is planned. label Sep 6, 2019
@bopazyn
Copy link
Author

bopazyn commented Sep 7, 2019

My tests have shown that attaching before queries works as expected. Thank you!

@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported
Projects
None yet
Development

No branches or pull requests

3 participants