EF 6 可选 FK ,删除仍然报错

EF 6 optional FK , delete still produces error

所以我有这两个简单的模型

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

    private string _Name;
    [Column("sNameColumn")]
    public string Name { get { return _Name; } set { _Name = value; } }

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

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int? blog_id { get; set; }

    [ForeignKey("blog_id")]
    public virtual Blog Blog { get; set; }
}

我没有对 dbContext 定义做任何异常的事情。然后,我尝试做这样的事情。

 db.Blogs.Remove(db.Blogs.Find(2)); 
 db.SaveChanges();

我发现 FK 违规 error.Notice FK blog_id 可以为空,所以我认为 EF 会处理删除,并使相应的 FK 为空。 你能告诉我我错过了什么吗?

必须为 EF 加载实体才能处理将其外键设置为 null。

var b = db.Blogs.Find(2);
db.Entry(b).Collection(b => b.Posts).Load();
db.Blogs.Remove(b); 
db.SaveChanges();

请记住,Entity Framework 只能更新它已加载的实体。

当然有一些方法可以通过原始 SQL 语句更新数据库记录,您也可以通过 EF 执行这些语句,但这不是作为 ORM 的 EF 的核心。

所以如果你只想使用 EF,你别无选择。您必须显式加载 Blogs 中的集合,以便它们与父级分离。例如 Include:

var b = db.Blogs.Include(b => b.Posts).Include(b => b.Comments)
          .Single(b => b.BlogId == 2);
db.Blogs.Remove(b); 
db.SaveChanges();

或通过 Load 在其他答案中。

另一种选择是使用 Entity Framework Extented。它的功能之一是批量更新,它允许在给定模板记录的 IQueryable 中一次性更新记录语句。这看起来像这样:

using EntityFramework.Extensions;
...
db.Posts.Where(p => p.BlogId == 2)
        .Update(p => new Post { BlogId = default(int?) });
db.Blogs.Remove(b); 
db.SaveChanges();

仅修改模板记录中设置的属性。要使此事务具有事务性,您应该将所有语句包装在 TransactionScope.