简体   繁体   English

EF Core-从集合导航属性中删除相关实体不会更新数据库

[英]EF Core - Removing a related entity from collection navigation property does not update database

I am trying to understand this sentence: 我试图理解这句话:

By default, for required relationships, a cascade delete behavior is configured and the child/dependent entity will be deleted from the database. 默认情况下,对于必需的关系,将配置级联删除行为,并且将从数据库中删除子级/从属实体。

found in the "Removing relationships" paragraph in this Microsoft documentation of EF Core: https://docs.microsoft.com/en-us/ef/core/saving/related-data#removing-relationships 在EF Core的此Microsoft文档的“删除关系”段落中找到: https : //docs.microsoft.com/zh-cn/ef/core/saving/related-data#removing-relationships

On a .Net Core API, with a model of blog and posts as follows 在.Net Core API上,其博客和帖子模型如下

public class Blog
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int BlogId { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

public class Post
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int PostId { get; set; }

    public int BlogId { get; set; }
    public virtual Blog Blog { get; set; }
}

When I retrieve a blog by id through 当我通过ID通过ID检索博客时

[HttpGet("{id}")]
public async Task<IActionResult> GetBlog([FromRoute] int id)
{
    return await context.Blog.Where(b => b.BlogId == id)
                             .Include(b => b.Posts).FirstOrDefaultAsync();
}

I receive in JSON 我收到JSON

{
  "BlogId": 1,
  "Posts": [
    {
      "PostId": 1
    },
    {
      "PostId": 2
    }
  ]
}

When I send back to the API the updated following JSON to be persisted in the database 当我发回API时,更新后的以下JSON将保留在数据库中

{
  "BlogId": 1,
  "Posts": [
    {
      "PostId": 2
    }
  ]
}

to

[HttpPut("{id}")]
public async Task<IActionResult> PutBlog([FromRoute] int id, [FromBody] Blog blog)
{
    this.context.Update(blog);
    await this.context.SaveChangesAsync();

    return this.Ok();
}

Everything runs fine but no entries are modified. 一切运行正常,但没有任何条目被修改。

As the relationship from a post to a blog is required and the related post is removed from the blog collection-of-posts property, shouldn't post with PostId = 1 be deleted from the database? 由于需要从帖子到博客的关系,并且已从Blog的collection-of-posts属性中删除了相关的帖子,因此是否应该从数据库中删除PostId = 1的帖子?

What really confuses me is that, as soon as I use a many-to-many relationship between blogs and posts, not changing anything else in the logic, the entry in table Blog_Post where PostId = 1 is actually deleted. 真正令我困惑的是,只要我在博客和帖子之间使用多对多关系,而没有在逻辑上进行任何其他更改,则实际上会删除表Blog_Post中PostId = 1的条目。

Update merely associates the entity and marks all properties as modified. Update仅关联实体并将所有属性标记为已修改。 AFAIK it does not cascade down, or affect child collections. AFAIK它不会层叠下来,也不会影响子集合。

As a general rule you should avoid passing entities to and from a web client. 通常,您应避免将实体与Web客户端之间来回传递。 If you accept an entity to a web client, it is a simple matter to find the call passing the modified entity to the server, apply a breakpoint, and modify the contents using the debugger before resuming. 如果您接受Web客户端的实体,则很简单的事情就是找到将已修改的实体传递给服务器的调用,应用断点,并在继续之前使用调试器修改内容。 If the server merely attaches the entity to a context and saves the changes, I can modify data in ways the application should not allow. 如果服务器仅将实体附加到上下文并保存更改,则可以按照应用程序不允许的方式修改数据。 It also involves sending more information to/from the client than is typically necessary. 它还涉及向客户端发送/从客户端发送比通常所需更多的信息。

Regarding the behaviour for deleting orphans, this applies when you modify the collections. 关于删除孤儿的行为,在修改集合时适用。 You can find an example of detecting entities to add & remove and applying those changes in my response to this question. 您可以找到一个示例来检测要添加和删除的实体,并在我对此问题的回复中应用这些更改。

Enity Framework delete related entities from principle Entity to Dependent Entity. Enity Framework从原则实体到从属实体删除相关实体。 In your Case Principle is the Blog and Post is the dependent entity. 在您的案例中,原则是Blog,而Post是从属实体。 By Deleting Blog related Posts should also be deleted. 通过删除Blog相关帖子也应删除。 You also need to decorate with Foreign key attribute, your class in that case will look like this. 您还需要使用外键属性进行修饰,在这种情况下,您的类将如下所示。

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public int BlogForeignKey { get; set; }
    [ForeignKey("BlogForeignKey")]
    public Blog Blog { get; set; }
}

You also need to define delete behaviour, you can do this by using Fluent API setting, Cascade will delete related entity, if you don't want to delete related entity then use ClientSetNull , it will 您还需要定义删除行为,可以使用Fluent API设置来执行此操作,Cascade会删除相关实体,如果您不想删除相关实体,请使用ClientSetNull,它将

model.Entity<Post>().HasOne(p => p.Blog).WithMany(b => b.Posts)
    .HasForeignKey(p => p. BlogForeignKey)
    .OnDelete(DeleteBehavior.Cascade);

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

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