Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Entity Framework insert children when I update the parent?

I have this code in a Windows Service targeted to .Net 4.5 that uses a database-first Entity Framework layer:

var existingState = DataProcessor.GetProcessState(workerId);

existingState.ProcessStatusTypeId = (int)status;
existingState.PercentProgress = percentProgress;
existingState.ProgressLog = log;

DataProcessor.UpdateProcessState(existingState);

And this code in a data processing class in the same solution:

public ProcessState GetProcessState(int id)
{
    using (var context = new TaskManagerEntities())
    {
        var processes = (from p in context.ProcessStates.Include("ProcessType").Include("ProcessStatusType")
                         where p.IsActive && p.ProcessStateId == id
                         select p);

        return processes.FirstOrDefault();
    }
}

public ProcessState UpdateProcessState(ProcessState processState)
{
    using (var context = new TaskManagerEntities())
    {
        context.ProcessStates.Add(processState);
        context.Entry(processState).State = System.Data.EntityState.Modified;
        context.SaveChanges();
    }

    return processState;
}

ProcessState is a parent to two other classes, ProcessStatusType and ProcessType. When I run that code in the windows service, it retrieves a record, updates the entity and saves it. Despite the fact that the ProcessType child is never used in the above code, when the save on the ProcessState entity is performed, EF does an insert on the ProcessType table and creates a new record in it. It then changes the FK in the ProcessStatus entity to point it at the new child and saves it to the database.

It does not do this in the ProcessStatusType table, which is set up with an essentially identical FK parent-child relationship.

I now have a database full of identical ProcessType entries that I don't need, and I don't know why this is occurring. I feel like I'm making some obvious mistake that I can't see because this is my first EF project. Is the issue that I'm allowing the context to expire in between calls but maintaining the same entity?

like image 558
RedBrogdon Avatar asked Feb 15 '13 19:02

RedBrogdon


People also ask

How does Entity Framework update work?

Updating Data In the connected scenario, EF API keeps track of all the entities retrieved using a context. Therefore, when you edit entity data, EF automatically marks EntityState to Modified , which results in an updated statement in the database when you call the SaveChanges() method.

How do you update related entities in Entity Framework Core?

This can be achieved in several ways: setting the EntityState for the entity explicitly; using the DbContext. Update method (which is new in EF Core); using the DbContext. Attach method and then "walking the object graph" to set the state of individual properties within the graph explicitly.

How do I update my entity model?

In the Model Browser, right-click the . edmx file and select Update Model from Database. Expand the Tables, Views, and Stored Procedures nodes, and check the objects you want to add to the . edmx file.


1 Answers

Using Add will set the state of all elements to Added, which is causing the child elements to be inserted. The parent element is not inserted as you specify EntityState.Modified for this element.

Try using the following in the UpdateProcessState rather than using Add.

context.ProcessStates.Attach(processState);
context.Entry(processState).State = EntityState.Modified;
context.SaveChanges();

Attach will set the state of all elements to Unchanged and by specifying Modified for the parent element you are indicating that only this element should be updated.

On another note. You should use the strongly-typed Include(x => x.ProcessType) rather than Include("ProcessType").

like image 154
Martin4ndersen Avatar answered Oct 21 '22 08:10

Martin4ndersen