2

With Entity Framework 6, with the following classes and DbContext configuration of a Many-to-Many "join table", changes are being made OK, but no ChangeTracker entries are being created. Having tapped into the DbContext SaveChanges() for logging purposes I'd like to be able to log changes to this join FooBar table too.

Probably has something to do with a combination of this join table not having an actual POCO class and DbSet in my DbContext, and/or how ChangeTracker only tracks scalar properties.

public class Foo
{
    [Key]
    public long FooId { get; set; }

    public virtual ICollection<Bar> Bars { get; set; }
}

public class Bar
{
    [Key]
    public long BarId { get; set; }

    public virtual ICollection<Foo> Foos { get; set; }
}

DbContext configuration:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Foo>()
    .HasMany(foo => foo.Bars)
    .WithMany(bar => bar.Foos)
    .Map(x =>
    {
        x.MapLeftKey("FooId");
        x.MapRightKey("BarId");
        x.ToTable("FooBar");
    })
    .MapToStoredProcedures();

    modelBuilder.Entity<Bar>().MapToStoredProcedures();
}

If I have an existing Foo "foo", a bunch of Bars, and make changes to the "foo.Bars" collection to link those Bars to my Foo. SaveChanges() is saving the changes perfectly for both adds and deletes in the FooBar table, but the "foo" entity is set to EntityState.Unmodified in ChangeTracker. If I manually set it to EntityState.Modified, the changes get persisted just like before, but its not really helping me since I need to log changes to the Foo.Bars collection. On adding brand new Foo's with the Bars collection filled in, no extra ChangeTracker records are being added to track the added FooBar records either.

One other obscure thing I tried was something from that Programming DbContext book, to try to use the ObjectContext.ObjectStateManager to set a relationship to modified manually.

((IObjectContextAdapter) PulseContext).ObjectContext
    .ObjectStateManager
    .ChangeRelationshipState(
        foo,
        foo.Bars,
        x => x.Bars,
        EntityState.Modified);

Similar to an example I found although that would probably set the entire "Foo.Bars" collection to Modified (if that was such a thing EF supported)... Where as I'd really like to get a separate ChangeTracker record for each individual FooBar contained in the Foo.Bars if that makes any sense. In any case, the above attempt got me this error:

The ObjectStateManager does not contain an ObjectStateEntry with a reference to an object of type 'System.Collections.Generic.HashSet`1[[XYZ.Foo.Bar, XYZ.Foo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'.

Maybe I can't really get FooBar ChangeTracker entries without concrete FooBar class and creating a DbSet for it in my DbContext, which seems a bit excessive for a simple join table and will probably complicate me adding/removing Bars to a foo's foo.Bars. I do have some other One-to-Many tables that do have their own DbSets which are being ChangeTracked just fine.

Cheers!

Jeremy
  • 388
  • 1
  • 4
  • 12

1 Answers1

2

The change tracker of DB context only holds information on changed entities, and not on changed relationships.

You were on the right way when trying to use the ObjectStateManager, and someone has doen it successfully:

Entity Framework 4.1+ many-to-many relationships change tracking

Community
  • 1
  • 1
JotaBe
  • 38,030
  • 8
  • 98
  • 117