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

时间:2019-03-11 20:37:39

标签: c# entity-framework asp.net-core entity-framework-core

我试图理解这句话:

  

默认情况下,对于必需的关系,将配置级联删除行为,并且将从数据库中删除子/相关实体。

在EF Core的此Microsoft文档的“删除关系”段落中找到:https://docs.microsoft.com/en-us/ef/core/saving/related-data#removing-relationships

在.Net Core API上,具有如下博客和帖子模型

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

当我通过ID通过ID检索博客时

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

我收到JSON

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

当我发回API时,更新后的以下JSON将保留在数据库中

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

    return this.Ok();
}

$stmt = $conn->prepare ("UPDATE tblx (fldx, fldx, fldx fldx) VALUES ( ?, ?, ?, ?)");
$stmt->bind_param("ssss", $, $, $, $); 
$stmt->execute();
$result = mysqli_stmt_get_result($stmt) or die ("");

一切正常,但没有条目被修改。

由于需要从帖子到博客的关系,并且相关帖子已从Blog-of-posts属性中删除,因此是否应该从数据库中删除PostId = 1的帖子? >

真正让我感到困惑的是,只要我在博客和帖子之间使用多对多关系,而没有改变逻辑上的任何其他内容,则实际上会删除表Blog_Post中PostId = 1的条目。

2 个答案:

答案 0 :(得分:0)

Update仅关联实体并将所有属性标记为已修改。 AFAIK不会降低或影响子集合。

作为一般规则,您应该避免将实体与Web客户端之间来回传递。如果您接受Web客户端的实体,则很简单的事情就是找到将已修改的实体传递给服务器的调用,应用断点,并在继续之前使用调试器修改内容。如果服务器仅将实体附加到上下文并保存更改,则可以按照应用程序不允许的方式修改数据。它还需要向客户端发送/从客户端发送比通常所需更多的信息。

关于删除孤儿的行为,这在修改集合时适用。您可以找到一个示例,该示例检测我要添加和删除的实体并将这些更改应用于我对this问题的回答。

答案 1 :(得分:0)

实体框架从原则实体到从属实体删除相关实体。在您的案例中,原则是Blog,而Post是从属实体。通过删除Blog相关帖子也应删除。 您还需要使用外键属性进行修饰,在这种情况下,您的类将如下所示。

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; }
}

您还需要定义删除行为,您可以使用Fluent API设置来执行此操作,Cascade会删除相关实体,如果您不想删除相关实体,请使用ClientSetNull,它将

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