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。