Entity Framework will only save navigation properties for new entities, not updates

c# entity-framework entity-framework-6 navigation-properties

Question

I tried loading the navigation properties first by using Include, and I ensured that the children were loaded.

For new items, I can add a child navigation set with no issues. For updated items, I tried to pass in a completely new collection to overwrite the list, but I read that I needed to work with the loaded collection. Even after clearing the collection and adding to it, I do not see any changes reflected.

For all entities in my project, I am calling a generic method which has these lines and some error handling logic, but no errors are thrown:

Save() method:

context.Set<T>().AddOrUpdate(entities);
context.SaveChanges();

Use:

    var entities = repository.LoadWithIncludes(x =>.Subset1);
    var entity = entities.FirstOrDefault(x => x.ID == id) ?? new Entity{ID = id};

    entity.Subset1.Clear();

    var IDs = GetIDs(id) ?? Array.Empty<int?>();
    foreach (var id in IDs)
       {
           entity.Subset1.Add(new Subset
             {
               ParentId = id,
               Value = part1;
             });
        }

// then I pass the new and updated items into an array and call the Save() method above

The LoadWithIncludes method is taken from this answer: https://stackoverflow.com/a/18805096/7096114

1
0
8/4/2017 6:23:20 PM

Popular Answer

The AddOrUpdate Method

This method is supposed to be used when seeding your database. Which leads me to think you're going to get some poor behaviors.

Let's go start with correcting the way you are updating the context...

public void Edit(Entity entity)
{
    var db = context
        .Include(i => i.Subset1)
        .Where(i => i.ID == id)
        .Single();

    // update entity
    context.Entry(db).CurrentValues.SetValues(entity);

    // delete / clear subset1 from database
    foreach (var dbSubset1 in db.Subset1.ToList())
    {
        if (!entity.Subset1.Any(i => i.ID == dbSubset1.ID))
            context.Subset1.Remove(dbSubset1);
    }

    foreach (var newSubset1 in entity.Subset1)
    {
        var dbSubset1 = db.Subset1.SingleOrDefault(i => i.ID == newSubset1.Id);
        if (dbSubset1 != null)
            // update Subset1
            context.Entry(dbSubset1).CurrentValues.SetValues(newSubset1);
        else
            db.Subset1.Add(newSubset1);
    }

    // save
    db.SaveChanges();
}

There is a great article on how to get this done in a much cleaner way, which involves making a method just to deal with the navigation property in the Microsoft Docs here (look about 3/4 of the way down the article for the example).

Here is also a quote from the docs.

For most relationships, this can be done by updating either foreign key fields or navigation properties. For many-to-many relationships, the Entity Framework doesn't expose the join table directly, so you add and remove entities to and from the appropriate navigation properties.

1
8/4/2017 7:03:56 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow