如何清除()实体框架ICollection中的所有元素?

时间:2016-10-05 08:02:33

标签: c# entity-framework icollection

我在使用Clear()

从实体框架中删除集合中的所有元素时遇到问题

考虑一下常用的博客和帖子示例。

public class Blog
{
    public int Id {get; set;}
    public string Name {get; set;}
    public virtual ICollection<Post> Posts { get; set; }
}

public class Post
{
    public int Id { get; set; }

    // foreign key to Blog:
    public int BlogId { get; set; } 
    public virtual Blog Blog { get; set; }

    public string Title { get; set; }
    public string Text { get; set; }
}

public class BlogContext : DbContext
{
    public DbSet<Blog> Blogs {get; set;}
    public DbSet<Post> Posts {get; set;}
}

博客有很多帖子。博客有一个ICollection的帖子。博客和帖子之间存在直接的一对多关系。

假设我要删除博客中的所有帖子

当然,我可以做到以下几点:

Blog myBlog = ...
var postsToRemove = dbContext.Posts.Where(post => post.BlogId == myBlog.Id);
dbContext.RemoveRange(postsToRemove);
dbContext.SaveChanges();

然而,以下似乎更容易:

Blog myBlog = ...
myBlog.Posts.Clear();
dbContext.SaveChanges();

但是这会导致InvalidOperationException:

操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为foreign-key属性分配另一个非空值,或者必须删除不相关的对象。

清除收藏品的正确方法是什么?是否有一个流畅的API声明?

2 个答案:

答案 0 :(得分:6)

两个代码示例之间存在差异。

您的第一个代码示例dbContext.RemoveRange(postsToRemove)会删除Post条记录。因此,任何涉及这些记录的关系也将被删除。

在您的第二个代码示例myBlog.Posts.Clear()中,您将删除myBlog与其对应的Post记录之间的关系。真实的&#39;基本操作是将BlogId记录的Post值设置为null。不幸的是,这是不可能的,因为BlogId设置为不可为空。因此,简而言之,关系将被删除,并且实际上不会删除任何记录。

答案 1 :(得分:2)

Clear处理关系,而不是删除实体。

你写的两个解决方案之间有一个工作(我认为更具可读性)的中途解决方案。

dbContext.Posts.RemoveRange(myBlog.Posts);
// Now (also before SaveChanges) the myBlog.Posts is empty
dbContext.SaveChanges();

修改
RemoveRange还会从Blog.Posts集合

中删除帖子