Entity Framework Core系列之DbContext(删除)

上一篇我们介绍了Entity Framework Core系列之DbContext(修改),这一篇我们介绍下删除数据

修改实体的方法取决于context是否正在跟踪需要删除的实体。

下面的示例中context获得了需要删除的实体对象,所以context会开始追踪这个实体。DbContext.Remove方法会将实体的EntityState设置成deleted

context.Remove(context.Authors.Single(a => a.AuthorId == 1));
context.SaveChanges();

当SaveChanges被调用时,数据库生成并执行delete语句

exec sp_executesql N'SET NOCOUNT ON;
DELETE FROM [Authors]
WHERE [AuthorId] = @p0;
SELECT @@ROWCOUNT;
',N'@p0 int',@p0=1

这种方法实际上执行了两个sql语句,一个用于从数据库检索实体,另一个用于删除实体,您可以使用存根来表示要删除的实体,从而停止从数据库检索的实体:

 using (var context = new EFCoreContext())
            {
                var author = new Author { AuthorId = 1 };
                context.Remove(author);
                context.SaveChanges();
            }

存根需要的唯一属性是主键值。

设置EntityState

可以通过EntityEntry显式地设置要删除的实体的EntityState的属性值

using (var context = new EFCoreContext())
            {
                var author = new Author { AuthorId = 1 };
                context.Entry(author).State = EntityState.Deleted;
                context.SaveChanges();
            }

多个相关实体

如果需要删除的实体有关联的数据,那就看这些关系是如何配置的,一个完全定义的关系将具有一个级联引用约束集来删除或SetNull,通过Fluent API配置的关系也是如此。在这些情况下,您可以删除主体并让数据库处理相关的行。当引用约束动作被设置为NoAction时,您需要显式地处理所有相关数据。下一个示例演示了在不包含外键属性的模型上配置的关系:

public class Author
{
   public int AuthorId { get; set; }
   public string FirstName { get; set; }
   public string LastName { get; set; }
   public ICollection<Book> Books { get; set; }
}

public class Book
{
   public int BookId { get; set; }
   public string Title { get; set; }
}

默认情况下,此关系被配置为可选的,引用约束操作选项被配置为NoAction。此外,EF Core引入了一个影子属性来表示外键。它被命名为AuthorId,并应用于Book实体,由于关系是可选的,所以AuthorId属性可以为nullable。为了删除Author,你需要删除每个Book和Author之间的关系。代码如下:

 using (var context = new EFCoreContext())
            {
                var author = context.Authors.Single(a => a.AuthorId == 1);
                var books = context.Books.Where(b => EF.Property<int>(b, "AuthorId") == 1);
                foreach (var book in books)
                {
                    author.Books.Remove(book);
                }
                context.Remove(author);
                context.SaveChanges();
            }

从数据库中检索Author,和它相关的Books也就被检索出来然后再逐一被remove出集合,然后执行context.Remove(author),最后结果会使相关的Book中的AuthorId设置成null。

exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Books] SET [AuthorId] = @p0
WHERE [BookId] = @p1;
SELECT @@ROWCOUNT;
UPDATE [Books] SET [AuthorId] = @p2
WHERE [BookId] = @p3;
SELECT @@ROWCOUNT;
UPDATE [Books] SET [AuthorId] = @p4
WHERE [BookId] = @p5;
SELECT @@ROWCOUNT;
',N'@p1 int,@p0 int,@p3 int,@p2 int,@p5 int,@p4 int',@p1=1,@p0=NULL,@p3=2,@p2=NULL,@p5=3,@p4=NULL
exec sp_executesql N'SET NOCOUNT ON;
DELETE FROM [Authors]
WHERE [AuthorId] = @p6;
SELECT @@ROWCOUNT;
',N'@p6 int',@p6=1

数据库执行了四次操作:查询Author,查询Book,更新Book,删除Author,因此,使用引用完整性约束将外键设置为null或删除依赖项是一个好主意o。

posted @ 2018-07-06 11:36  yixuan.han  阅读(3548)  评论(0编辑  收藏  举报