'How to update parent with children, without changing children primary keys?
I have a following one-to-many structure:
public class City
{
public City()
{
this.Schools = new List<School>();
}
public int Id { get; set; }
public virtual ICollection<School> Schools { get; set; }
}
public class School
{
public int Id { get; set; }
public int CityId { get; set; }
public string Data { get; set; }
}
My problem: when I'm updating City that includes a School collection, everything works great, but primary keys for each school changes. It's like EF first update changes in the City entity, then deletes all schools and then adds cities from request.
I understand that EF can't recognize which schools changed, which were added or removed, so that's why I does what it does, but here is my question:
How can I prevent EF from touching the School collection at all? Just change the City and I can handle changes in schools manually. I was trying this, but it still changes city along with all schools:
public override void Update(City city)
{
var existingCity = _context.Cities
.Include(p => p.Schools)
.FirstOrDefault(p => p.CityId == city.CityId);
if (existingCity != null)
{
_context.Entry(existingCity).CurrentValues.SetValues(city);
_context.SaveChanges();
}
}
To clarify, this is what I'm looking for:
When parent with children is being deleted - I want to keep CascadeDelete and delete children
When parent with children is being inserted - I want to insert parent and children
When parent with children is being updated - I want to update only parent. I don't want to touch children.
#1 and #2 works for me. I have a problem with #3.
Solution 1:[1]
In your DbContext.OnModelCreating(ModelBuilder modelBuilder) you could specify how EF will handle child entities once the parent entity has been deleted;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<City>()
.HasMany(c => c.Schools)
.WithOne(c => c.City)
.OnDelete(DeleteBehavior.ClientNoAction);
}
In your school class, you might need to add a navigation property to City;
public class School
{
public int Id { get; set; }
public int CityId { get; set; }
[ForeignKey("CityId")]
public City City { get; set; }
public string Data { get; set; }
}
Also in your code, it looks like you are replacing the entire entity including its navigation properties. I suggest you update individual properties;
public override void Update(City city)
{
var existingCity = _context.Cities
.Include(p => p.Schools)
.FirstOrDefault(p => p.CityId == city.CityId);
if (existingCity != null)
{
// you could update individual properties only
existingCity.CityId = city.CityId;
_context.SaveChanges();
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Jerdine Sabio |
