kamayd
kamayd

Reputation: 440

How to properly Delete fields of an Entity?

I am having trouble when trying to delete a field of an Entity using Entity Framework (version 6.1.3).

Let's say I have two Entities: Person and Work. I can change the work of a person without any issue, but when I try to express that the person is unemployed it does not work properly:

 person.Work = null;
 db.SaveChanges();

After running this code the person still will have the previous work, but if I use the debugger and check the Work property of person before running person.Work = null;, everything will behave as expected.

Can someone please explain why reading the value first makes the code work properly and how to correctly delete the field?

 var work = person.Work; \\ with this line here everything works as expected
 person.Work = null;
 db.SaveChanges();

Upvotes: 0

Views: 416

Answers (2)

jjj
jjj

Reputation: 4997

Two things that are contributing to your issue:

  1. Entity Framework determines what needs to updated during SaveChanges by tracking changes to property values.
  2. You probably have lazy loading enabled (both in general and for the Work property), which means that if the person has an associated Work, that associated entity doesn't get loaded until the first time you access that property.

Putting those together, when you set person.Work = null without accessing person.Work (which would trigger a load), the context thinks nothing has changed. But if you load the property first, setting the property to null tells EF to remove that association. Edit: According to the page that octavioccl linked, this is true for .NET 4.0., but for .NET 4.5+ (and EF 5+), loading first is unneeded.

Possible solutions

  1. If you want to remove the association without loading the related entity, you'll need to add a foreign key property to your Person entity, then you can set that to null instead of setting the navigation property to null. For example:

    public class Person
    {
        // other properties...
        public int? WorkId { get; set; }
        public virtual Work { get; set; }
    }
    
    person.WorkId = null;
    db.SaveChanges();
    
  2. octavioccl's answer quoted another option:

    context.Entry(person).Reference(p => p.Work).CurrentValue = null;

Upvotes: 1

ocuenca
ocuenca

Reputation: 39326

From this msdn page:

To delete the relationship, set the navigation property to null. If you are working with the Entity Framework that is based on .NET 4.0, then the related end needs to be loaded before you set it to null. For example:

context.Entry(person).Reference(p => p.Work).Load();
person.Work = null;

Starting with the Entity Framework 5.0, that is based on .NET 4.5, you can set the relationship to null without loading the related end. You can also set the current value to null using the following method:

context.Entry(person).Reference(p => p.Work).CurrentValue = null;

Upvotes: 0

Related Questions