when i try to attach entity to context i get an exception
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key
This is expected behaviour.
But i would like to know how ObjectStateManager knows that? I would like to do this check by myself before
Although the DbContext implements IDisposable , you shouldn't manually dispose it, nor should you wrap it in a using statement. DbContext manages its own lifetime; when your data access request is completed, DbContext will automatically close the database connection for you.
SaveChanges() This method will automatically call DetectChanges() to discover any changes to entity instances before saving to the underlying database. This can be disabled via AutoDetectChangesEnabled. Entity Framework Core does not support multiple parallel operations being run on the same DbContext instance.
The OnConfiguring() method allows us to select and configure the data source to be used with a context using DbContextOptionsBuilder . Learn how to configure a DbContext class at here.
EF and EF Core DbContext types implement IDisposable . As such, best practice programming suggests that you should wrap them in a using() block (or new C# 8 using statement). Unfortunately, doing this, at least in web apps, is generally a bad idea.
If you are using DbContext API (you mentioned ef-code-first) you can simply use:
context.YourEntities.Local.Any(e => e.Id == id);
or more complex
context.ChangeTracker.Entries<YourEntity>().Any(e => e.Entity.Id == id);
In case of ObjectContext API you can use:
context.ObjectStateManager.GetObjectStateEntries(~EntityState.Detached) .Where(e => !e.IsRelationship) .Select(e => e.Entity) .OfType<YourEntity>() .Any(x => x.Id == id);
Here's an extension method for getting the object from the context without having to worry about whether it is already attached:
public static T GetLocalOrAttach<T>(this DbSet<T> collection, Func<T, bool> searchLocalQuery, Func<T> getAttachItem) where T : class { T localEntity = collection.Local.FirstOrDefault(searchLocalQuery); if (localEntity == null) { localEntity = getAttachItem(); collection.Attach(localEntity); } return localEntity; }
Just call:
UserProfile user = dbContext.UserProfiles.GetLocalOrAttach<UserProfile>(u => u.UserId == userId, () => new UserProfile { UserId = userId });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With