简体   繁体   中英

Entity Framework Relationships Not Updating

I am having a problem where by updating an entity does not update entities related to it. Here is an example of the code.

public class Foo
{
    public int Id { get; set; }
    public virtual ICollection<Bar> Bars { get; set; }
    public virtual string SomeString { get; set; }
}

public class Bar
{
    public int Id { get; set; }
}

public class FooMapping : EntityTypeConfiguration<Foo>
{
    public FooMapping()
    {
        HasKey(f => f.Id);
        HasMany(f => f.Bars);
    }
 }


public class MyDb : DbContext
{
    public IDbSet<Foo> Foos { get; set; }
    public IDbSet<Bar> Bars { get; set; }

    protected override vod OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Configurations.Add(new FooMapping());
    }
}

I receive an update command containg a fooobject from an external application like this:

public void Update(Foo foo)
{
    _myDb.Entry(foo).State = EntityState.Modified;
    _myDb.SaveChanges();
}

This updates the SomeString value correctly, however the Bar objects are not modified.

I have tried doing the following:

public void Update(Foo foo)
{
    foreach(Bar bar in foo.Bars)
    {
        _myDb.Entry(bar).State = EntityState.Modified;
    }

    _myDb.Entry(foo).State = EntityState.Modified;
    _myDb.SaveChanges();
}

but this gives a DbUpdateConcurrencyException , with the following info

Store update, insert, or delete statement affected an unexpected
number of rows (0). 
Entities may have been modified or deleted since entities were loaded. Refresh 
ObjectStateManager entries.

How can I get the Bars to update without having to select them from the database?

Thanks

UPDATE

I have modified the Bar entity and the mappings as so.

public class Bar
{
    public int Id { get; set; }
    public virtual Foo Foo { get; set; }
}

public class FooMapping : EntityTypeConfiguration<Foo>
{
    public FooMapping()
    {
        HasKey(f => f.Id);
        HasMany(f => f.Bars).WithRequired(b => b.Foo);
    }
 }

public class BarMapping : EntityTypeConfiguration<Foo>
{
    public BarMapping()
    {
        HasKey(b => b.Id);
        HasRequired(b => b.Foo);
    }
 }

This doesn't change the anything. I should mention though that even with the first version using _myDb.Foos.Add(foo) works correctly (adding all Bars). However it is the update which does not.

You may notice that if Foo has new Bar items they will be added and (possibly) the existing ones will be nullified. You can try a few things:

Relate Bar to Foo:

public class Bar
{
    public int Id { get; set; }

    public virtual Foo Foo { get; set; }
}

public class FooMapping : EntityTypeConfiguration<Foo>
{
    public FooMapping()
    {
        HasKey(f => f.Id);
        HasMany(f => f.Bars)
            .WithRequired(b => b.Foo); //check this syntax, I'm not entirely sure.
    }
}

Try the above. What happened when I had a similar problem was that the "new" Bars where saved and the existing ones where nullified.

The next step you can try is to do a bit of manual deletion when updating:

public void Update(Foo foo)
{
    var existing = _myDb.Find(foo.Id);
    foreach(Bar bar in existing.Bars.ToList()) 
    {
        _myDb.Remove(bar);
    }
    existing.Bars.Clear();
    foreach(Bar bar in foo.Bars)
    {
        existing.Bars.Add(bar);
    }
    // map other properties...
    _myDb.SaveChanges();
}

Let me know if it works for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM