Entity Framework duplicating class when trying to insert related entity - c#

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

Related

EF Core is sharing tracked entities across instances

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.

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.

How to save it in entity right

Assume i have a big entity and want to create a typical CRUD application. A user shouldn't have the ability to save some fields of my entity.
So i see two ways to implement change-save logic:
a)
Get entity from DB
Out to page with all fields(fields which user shoudnt change outed as hidden inputs)
Take entity by post method
Attach to context and save
In this case i need to out on page useless fields. And it is sucks no doubt.
b)
Get entity from DB
Out to page only necessary fields(fields which user can change)
Take entity by post method
Get entity from DB
Fill DB entity by new values and save
In this case i need to do additional query to DB. So it is not good for perfomance.
What is right way?
or C):
Get entity from DB
Map entity to ViewModel with only the allowed fields
Post ViewModel with data back to controller
Map ViewModel back to Entity
Attach and Save.
EDIT:
I highly recommend AutoMapper for the mapping to and fro
Interestingly enough, I just watched a video made by Julie Lerman in which she discusses almost the exact same problem. Neither of your solutions was what she went with:
Have a separate entity class that contains the fields that you want to go on the screen, but still maps to the same table that the regular one does. Then just query that DbSet for grabbing the entity (with only those fields), and save the updates to that.
She mentioned this while discussing implementing Domain Driven Design on top of Entity Framework. So that if you have different DbContexts for different functions in your application, you can still have a DbContext that you're using write to the table, but you can restrict which fields that context can write to.
It is recommended to use different ViewModels for different tasks. If you want to show the user some fields of the Model to edit, then you can do so using EditModel and while saving use CreateModel to create and populate the database. This way you can avoid your database structure to be known to the user, thus ensuring protection and security.

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.

Issue adding an inherited object in Entity Framework

I am working on a small project using Entity Framework. I have a Group entity and a MissionTrip:Group entity (and also a SmallGroup:Group entity but that shouldn't be necessary information). I am using Table-Per-type inheritance set up analogously to the inheritance in this blog post by Muhammed Mosa.
I can't save a MissionTrip to the GroupSet using AddObject("GroupSet", missionTrip) or AddToGroupSet(missionTrip).
The MissionTrip object I am trying to save is a new, valid MissionTrip. The AddObject method does not throw any exception or give any indication that it did not work yet the object is not persisted to the database.
I am able to save un-hierarchical objects to the database using the exact same method but with correct results.
Let me know if more information would be helpful, any help would be appreciated
Edit
If it clarifies anything I am using the MySQL Data Provider.
I am able to retrieve MissionTrip typed objects from the GroupSet but am unable to add them. I cannot save instances of the other inherited type (SmallGroup) either.
I figured it out. The problem wasn't related to inheritance at all. I was calling SaveChanges from a different repository than the one that was tracking the change. I'm still pretty new to EF.

Categories

Resources