Yes there is a better approach. For a new person, use:
_context.People.Add(myPerson); //myPerson can have Pets attached
This will traverse all sub objects and mark them as NEW. When updating person, after calling the above code, you need to set which pet objects are modified/deleted.
I learned this in a Pluralsight course Entity Framework in the Enterprise. In it, Julie adds an extra field to Pets.
public enum ObjectState
{
Unchanged,
Added,
Deleted,
Modified
}
public interface IObjectWithState
{
[NotMapped]
[JsonIgnore]
ObjectState ObjectState { get; set; }
}
public class Pet : IObjectWithState
{
public int ID { get; set; }
public string Name { get; set; }
}
You might want this on all of your database entities.
In your repository
public void InsertOrUpdateGraph(Person entity)
{
_context.People.Add(entity);
if (entity.ID != default(int)) _context.ApplyStateChanges();
}
Some extensions
public static class ContextExtension
{
public static void ApplyStateChanges(this DbContext context)
{
foreach (var entry in context.ChangeTracker.Entries<IObjectWithState>())
{
IObjectWithState stateInfo = entry.Entity;
entry.State = stateInfo.ObjectState.ConvertState();
}
}
public static EntityState ConvertState(this ObjectState state)
{
switch (state)
{
case ObjectState.Modified:
return EntityState.Modified;
case ObjectState.Added:
return EntityState.Added;
case ObjectState.Deleted:
return EntityState.Deleted;
default:
return EntityState.Unchanged;
}
}
}
Works every time.