EF Core is sharing tracked entities across instances - c#

I am using EF Core 3.1.26 with EntityFrameworkCore.Jet 3.1.1, using MS Access for the database. I would update EF Core, but then it wouldn't be compatible with EntityFrameworkCore.Jet.
My problem is that there seems to be some kind of static cache shared across instances. When after creating a instance I attach a entity, it throws an error because the entity is already being tracked, even though it is the first entity attached to that context (the queries are marked with AsNoTracking). I even checked with the debugger that there are no entities in the Entries property of the Change Tracker.
Even when I execute SaveChanges(), entities are updated that shouldn't exist in that context, since I made no query whatsoever. In the Entries property there is only the entity I attached with is navigation properties to null. And yet a bunch of entities of different tables are updated. Those entities I did query, but in another context and with AsNoTracking.
I have no idea where EF Core or EntityFrameworkCore.Jet are getting this entities from. It is like Attach and SaveChanges are accessing a static Change Tracker, and I don't know how to solve this problem.
Thank you.
Edit: It was my mistake, I didn't check correctly.

Related

How to update / synchronize DbContext after external changes to the database

I am using Entity Framework 6 where, for performance reasons, I load my entities into my DbContext up front and then use them locally. Up to now, all changes to the database have gone through the DbContext so my local entities and the database have been in sync. However, I now have to call a Stored Procedure on the database, which has the side effects of making changes to tables (outside of the DbContext) that need to be reflected in my entities. By changes, I mean it is adding new records and deleting / updating existing records.
I do not want to dispose of my DbContext and create a new one, as some of the entity instances are wrapped within ViewModel classes. So, deleting the DbContext in this way would lead to major problems in the UI.
It is my understanding that simply calling Load() on all my DbSets of the DbContext will just replace the existing instances. So, any objects using the old entities instances won't work.
So, I thought I could use the Reload method like:
context.Entry(entity).Reload();
which would update my local entities, but I can only do this for the entities that the DbContext already knows about. It doesn't cover any NEW entities or DELETED entities that were created / deleted as a result of the Stored Procedure executing.
So, I am looking for a way to:
Load, from the database, entities that are NEW to my DbContext
Reload existing entities in my DbContext
Remove any deleted entities from my DbContext
Here is the official documentation for Entity Framework.
Starting from the analysis of your database situation, it suggests smart and quick ways to obtain what you want, detailing when necessary data-read strategies (like eager or lazy loading) or providing tutorials to correctly use code generation and the Wizard GUI.
http://www.entityframeworktutorial.net/choosing-development-approach-with-entity-framework.aspx
Here some more detailed info and tutorial on data-read strategies:
https://www.c-sharpcorner.com/article/eager-loading-lazy-loading-and-explicit-loading-in-entity-framework/
As I already told you in comments, I would suggest a database-first approach and with lazy loading to avoid uncontrolled data behaviours (or reloading the whole db when running a stored procedure).
Talking about the SP, it can simply be mapped through the Wizard that comes with Entity Framework and wrapped by a method.
Hope you will find these resources helpful!
In general EntityFramework can not aware on change in database and update dbcontext .there is no optimized or EntityFramework built-in solution for it.
I think you can use CDC in SqlServer, push change to your application and update your dbcontext. But it not acceptable solution for all business and senario

SQLite memory database eager loading entities

I've switched our tests to use a SQLite :memory: database over a database file in an effort to speed up our tests. Everything has gone smoothly, except for one caveat: it's automatically eagerly loading navigation properties on entities.
If I run the project and hit it with Postman using an actual database file, it doesn't eagerly load them, and only loads navigation properties if I specify I want them using .Include().
It didn't do this before I switched to a SQLite Memory database for the tests.
The DbContext configuration is as follows:
Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = false;
Configuration.ValidateOnSaveEnabled = true;
Has anyone run into this issue before?
This is an old post, but I thought I'd provide an answer for anyone else that stumbles upon this.
What is likely happening here is simply that your DbContext has the entities cached in its ChangeTracker. Regardless of the underlying provider, when you insert an entity into the database, Entity Framework tracks that entity. If you query for an entity you just inserted, Entity Framework assumes the entity would not have changed and therefore returns the entity from the ChangeTracker. If you changed your query to do a _myDbContext.Set<SomeEntity>().AsNoTracking().ToList() then you should find that it performs a query and only prefetches related entities you've specified.

How to add an entity without related entities, but saving relation?

As far as I understand, if I change a state of an entry in context like that:
context.Entry(doc).State = EntityState.Added;
the whole object graph behind doc will be set to EntityState.Added. That is how this mechanism described here:
Note that for all of these examples if the entity being added has
references to other entities that are not yet tracked then these new
entities will also be added to the context and will be inserted into
the database the next time that SaveChanges is called.
In my situation this behaviour is undesirable. When I receive doc entity, it's relations are already in database (were added in different context) and adding them again will cause an error. I need to add doc to a database with all references, but don't try to add other objects in graph.
Of course, I can iterate through all graph and set state explicitly, but does an easier way exist?
In Entity Framework Core, the behavior changed, calling:
context.Entry(asset).State = EntityState.Added;
will affect only the entity and not the related ones.
👉 I know the question is for Entity Framework classic (not Core), but surely will be more people using EF Core reaching here (like me) 😉
You may have a look at GraphDiff
According to this dedicated blog entry, it seems to fit your needs :
Say you have a Company which has many Contacts. A contact is not
defined on its own and is a One-To-Many (with required parent) record
of a Company. i.e. The company is the Aggregate Root. Assume you have
a detached Company graph with its Contacts attached and want to
reflect the state of this graph in the database.
At present using the Entity Framework you will need to perform the
updates of the contacts manually, check if each contact is new and
add, check if updated and edit, check if removed then delete it from
the database. Once you have to do this for a few different aggregates
in a large system you start to realize there must be a better, more
generic way.
Well good news is that after a few refactorings I've found a nice solution to this problem.

Entity Framework duplicating class when trying to insert related entity

I have an ASP.NET application with a view trying to update an existing entity's title, price, and another bool and string. I have a simple one to many relation of Modifier_Categories and Modifiers. Each Modifier_Category can have many Modifiers. Modifier is the entity I'm trying to update.
When I call dbContext.SaveChanges() it updates the Modifier entity like I want but then for some reason duplicates and inserts its related Modifier_Category entity.
Nowhere in my functions can I find anywhere that instantiates a new instance of the related Modifier_Category and inserts it using the dbContext.Modifier_Category.AddObject();
Is there a way to figure out when the context is getting a new entity attached? How is the entity being added without me stating I want to add it?
If you're using MVC there could be some model binding occurring that's creating that Modifier_Category entity and attaching it to your Modifier model. There's not really a good way to find out unless you just step through the code until you find it. You need to look for any situation in which your Modifier model has a Modifier_Category object added to it not just for that Modifier_Category object to be added to the context, because when you add/attach the Modifier entity it's going to try to add/attach any related objects tacked on to that model*.
*Provided those objects haven't been marked as not mapping back to your database

Entity Framework: Attaching related objects and other state management

I have an application which uses Entity Framework Code First. I am attempting to write my resource access layer. I have several objects which all have separate database tables and a lot of object relationships. Can someone point me to an up-to-date example of CRUD methods with related objects? Everything I have found uses an older version (I use DbContext, not ObjectContext, etc.) and I am having problems writing it myself.
For example, I am currently working on an object with a parent-child relationship with itself. I am attempting to write the Create method. If I use context.Objects.Add(newObject) then all the children objects also have their state changed to Added, which means that duplicate children are added. So I tried looping through all the children and attaching them to the context, but then any children that did not previously exist do not get added to the database and a DbUpdateException is thrown.
Is there a generic way I can attach all related entities and have their states be correct? Any help you can give me would be appreciated. Thanks!
Edit:
I tried explicitly loading the children using Load() and then adding the initial object. Unfortunately, it caused an exception because the parent comment had the child in its list of children but the parentID of the existing child had not yet been updated.
No there is no way to attach whole graph and let EF automatically set correct state - these problems didn't changed since ObjectContext API. You must always set state manually for each entity and relation or you must build the graph from attached entities. The only exception are Self tracking entities but they are not supported with DbContext API.

Categories

Resources