简体   繁体   English

如何在不更改子项主键的情况下用子项更新父项?

[英]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.我的问题:当我更新包含School集合的City时,一切都很好,但每所学校的主键都发生了变化。 It's like EF first update changes in the City entity, then deletes all schools and then adds cities from request.这就像 EF 首先更新City实体中的更改,然后删除所有学校,然后根据请求添加城市。

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:我知道 EF 无法识别哪些学校发生了变化,哪些学校被添加或删除了,所以这就是我做它所做的事情的原因,但这是我的问题:

How can I prevent EF from touching the School collection at all?我怎样才能完全防止 EF 接触School收藏? Just change the City and I can handle changes in schools manually.只需更改City ,我就可以手动处理学校的变化。 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:澄清一下,这就是我要找的:

  1. When parent with children is being deleted - I want to keep CascadeDelete and delete children当有孩子的父母被删除时 - 我想保留 CascadeDelete 并删除孩子

  2. When parent with children is being inserted - I want to insert parent and children当插入有孩子的父母时 - 我想插入父母和孩子

  3. 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. #1 和 #2 对我有用。 I have a problem with #3.我对#3 有疑问。

In your DbContext.OnModelCreating(ModelBuilder modelBuilder) you could specify how EF will handle child entities once the parent entity has been deleted;在您的DbContext.OnModelCreating(ModelBuilder modelBuilder) ,您可以指定删除父实体后 EF 将如何处理子实体;

https://learn.microsoft.com/en-us/do.net/api/microsoft.entityframeworkcore.deletebehavior?view=efcore-6.0 https://learn.microsoft.com/en-us/do.net/api/microsoft.entityframeworkcore.deletebehavior?view=efcore-6.0

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;在你的学校class,你可能需要给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();
   }
} 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM