C# – Updating sub-properties via Entity Framework

centity-frameworkormrelational-database

I was wondering how to updated nested objects/sub-properties when using Entity Framework. But to make things clear, let's start with an example.

I have an object, which can own a number of other objects. In other words, an object which contains a list of a different type of objects. This could be a person, who has multiple cars.

public class PersonModel
{
    // ...
    public List<CarModel> Cars { get; set; }
}

Now I want to make a service with a method called AddCar(), but I am a bit puzzled on what goes inside this method. It could look something like this:

public void AddCar(PersonModel owner, CarModel car)
{
    car.OwnerId = owner.Id;
    var ctx = GetDbContext();
    ctx.Cars.Add(car);
    ctx.SaveChanges();
}

Obviously this is a bit simplified, but you get the point. The problem in the example above is that the owner does not get updated. The new car will not be added to List<CarModel> Cars, until the person is re-loaded from the database.

This must be a common issue, so I suppose there is some sort of standard way of dealing with this. I just have not been able to find it. Here are the different solutions I can think of:

  • Make a method for updating the person from the database, which is called inside AddCar() (after adding the car).
  • Alter the object owner by adding the car to the list of cars, on top of adding it to the database (also inside AddCar()).
  • Add the new car to the list of cars inside owner and then make an update function which handles updating the owner, and all of its nested objects.

I cannot see any clear winnder in the suggestions above. Maybe it's something completely different? Any advice would be much appreciated.

Best Answer

This is totally up to your design. If you want to use Entity Framework AutoDetectChangesEnabled feature, it can be track changes and store for you. This property default value is true.

public PersonModel Person()
{
   // navigation property virtual ICollection<T>
   public virtual ICollection<CarModel> Cars { get; set; }
}

public void AddCar(PersonModel owner, CarModel car)
{

    var ctx = GetDbContext();
    PersonModel person = ctx.person.GetPerson(owner.Id);
    // this is entity object and entity framework will track the changes.
    // so when you add a car to person, then you can call save changes method
    person.Cars.Add(car);
    ctx.SaveChanges();

    foreach(CarModel car in person.Cars.ToList())
    {
        // Id will not be empty.
        Console.WriteLine(car.Id);
    }
}

Otherwise, you need to manage it manually:

public void AddCar(PersonModel owner, CarModel car)
{
    car.OwnerId = owner.Id;
    var ctx = GetDbContext();
    ctx.Cars.Add(car);
    ctx.SaveChanges();
    owner.Cars.Add(car);
}

I assume PersonModel is reference type. So, this referenced type instance owner includes new car. You can reach it from where you call AddCar method.

Note: I changed your Cars property to Navigation Propery. This is the best way to manage model relations(also table relations). Look at also Lazy Loading with Entity Framework.