Entity Framework - updating relationships by changing a foreign key

I have the following two models and DbContext:

public class TestDbContext : DbContext { public IDbSet<Person> People { get; set; } public IDbSet<Car> Cars { get; set; } } public class Person { public Person() { ID = Guid.NewGuid(); } public Guid ID { get; set; } public string Name { get; set; } public virtual List<Car> Cars { get; set; } } public class Car { public Car() { ID = Guid.NewGuid(); } public Guid ID { get; set; } public string Name { get; set; } public virtual Person Owner { get; set; } } 

Then I announce a list of people and a list of cars, setting the owner of the first car to the first person on the list:

 List<Person> People = new List<Person>() { new Person() {Name = "bill", ID = new Guid("6F39CC2B-1A09-4E27-B803-1304AFDB23E3")}, new Person() {Name = "ben", ID = new Guid("3EAE0303-39D9-4FD9-AF39-EC6DC73F630B")} }; List<Car> Cars = new List<Car>() { new Car() { Name = "Ford", Owner = People[0], ID = new Guid("625FAB6B-1D56-4F57-8C98-F9346F1BBBE4") } }; 

I store this in the database using the following code and it works fine.

 using (TestDbContext context = new TestDbContext()) { foreach (Person person in People) { if (!(context.People.Any(p => p.ID == person.ID))) context.People.Add(person); else { context.People.Attach(person); context.Entry<Person>(person).State = System.Data.EntityState.Modified; } } foreach (Car caar in Cars) { if (!(context.Cars.Any(c => c.ID == caar.ID))) context.Cars.Add(caar); else { context.Cars.Attach(caar); context.Entry<Car>(caar).State = System.Data.EntityState.Modified; } } context.SaveChanges(); } 

If I then changed the car owner to a second person and ran the code again, the property of the car owner will not be updated.

 Cars[0].Owner = People[1]; 

Any ideas what I'm doing wrong? Thanks for any help.

+7
c # relational-database orm entity-framework-5 entity-framework
source share
2 answers

I believe that this is a problem of an independent association of external relations . You are currently using an independent association, and the relationship between the car and the person is actually controlled by a separate recording object that has its own state (you must use the ObjectContext API to access this object). Setting the recording of a vehicle object to an altered state will not change the recording state for the relationship! A simple solution is to use a foreign key association instead, which means adding a new Guid PersonId to your car and displaying it as a foreign key property for the Person navigation property.

If you insist on using independent associations, you should change relations only on affiliates, otherwise you will have a severe headache with tracking these changes and installing all the necessary records with the correct state. This should be enough to create objects, attach them to the context, and only after that establish the owner of the car - I hope it will be tracked as a change.

+2
source share

Try something like this:

  using (TestDbContext context = new TestDbContext()) { foreach (Person person in People) { if (!(context.People.Any(p => p.ID == person.ID))) context.People.Add(person); else { context.People.Attach(person); context.Entry<Person>(person).State = System.Data.EntityState.Modified; } context.SaveChanges(); } foreach (Car caar in Cars) { if (!(context.Cars.Any(c => c.ID == caar.ID))) context.Cars.Add(caar); else { context.Cars.Attach(caar); context.Entry<Car>(caar).State = System.Data.EntityState.Modified; } context.SaveChanges(); } } 

I think your mistake is with context.SaveChanges placements (and partly of your architecture). Consider using a dedicated method (for example, a basic CRUD) for each operation in your database through the Entity Framework. Hope this helps.

Edit: Using CRUD:

 public class PersonManager // CRUD { public void Create(Person person) { using (TestDbContext context = new TestDbContext()) { context.Person.Add(person); context.SaveChanges(); } } public void Update(Person person) { using (TestDbContext context = new TestDbContext()) { context.Person.Attach(person); context.Entry(person).State = System.Data.EntityState.Modified; context.SaveChanges(); } } } 

You can also make this class static to fit your architecture.

0
source share

All Articles