Entity Framework doesn't seem to be able to properly link new navigation properties on updates

547 Views Asked by At

When I'm creating new entities, I'm able to use the unit of work pattern and create parent and children at the same time while EF handles the relationships and either saves the whole result or rolls it back.

When I'm doing an update via DbSet<Xyz>.Update(xyz), and xyz has been updated such that navigation property (Apple) is now a new entity (newApple), I can't find any way to establish this relationship. If I manually call DbSet<Apple>.Add(newApple), the new apple is added to the database. EF just didn't do anything with the fact that I've set xyz.Apple = newApple, and I'd expect it to be able to based on how it handles creates. I also tried setting xyz.AppleId = default, but that just sets it to null if there is a value and doesn't do anything if there wasn't one.

What am I missing?

note:

  1. Yes, I'm pulling the Apple property. That doesn't seem to make a difference.
  2. I have tried setting the specific property's IsModified value to true as well. That is actually what I originally hoped to do as I usually only want to update a few fields at a time. When that didn't work, I reverted back to using the Update method which also failed with the exact same issues (setting it to a default value if I cleared out the AppleId property and set xyz.Apple = new Apple).
  3. I've disabled AutoDetectChanges. I didn't think to mention it because I've done this for the last 7 or so years. Not sure that this makes a difference because my goal is to only explicitly inform EF of what I want it to operate on (I know that's not the recommended approach).

edit: Here's an actual code block so I can beat the "didn't try hard enough" accusations after staying up till 5am trying to make this work :)

// this just sets the  tree's apple id to the default value (null or 0) and adds the new apple to the db
var tree = db.Trees.Include(x => x.Apple).FirstOrDefault();
var newApple = new Apple();
db.Apples.Add(newApple);
tree.AppleId = default;
tree.Apple = newApple;
db.Trees.Update(tree);
db.SaveChanges(); 


// this adds the new apple to the db and doesn't modify the tree at all
var tree = db.Trees.Include(x => x.Apple).FirstOrDefault();
var newApple = new Apple();
db.Apples.Add(newApple);
tree.AppleId = default;
tree.Apple = newApple;

db.Entry(entity).Navigation(nameof(Apple)).IsModified = true;
// note: I've also tried setting AppleId property to IsModified just in case, but that will null it out. Without that, it doesn't change at all
db.SaveChanges(); 
0

There are 0 best solutions below