EF CORE DELETE

本文介绍了EF Core在删除操作中的处理方式,包括可选和必选关系的影响。对于可选关系,允许外键为null,而必选关系则不允许。删除时,EF Core会根据模型配置执行级联删除或设置外键为null。默认行为可能是级联或限制,但可以通过`OnModelCreating`方法自定义,例如设置为`DeleteBehavior.Cascade`以实现父类删除时同时删除子类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        public void Delete()
        {
            testDbContext.Order.Remove(testDbContext.Order.Find(1006));
            testDbContext.SaveChanges();
        }

这种方式会执行两次sql语句,第一次是将实体查询出来,第二次是执行删除语句

通过上下文查询出来的实体都会被标记一个状态Unchanged,再执行Remove方法时会标记状态为deleted,调用savechenges方法则会执行删除的sql语句。

 public void Delete1()
        {
            var order = new Order { OrderId = 1007 };
            testDbContext.Entry(order).State = EntityState.Deleted;
            testDbContext.SaveChanges();
        }

        public void Delete2()
        {
            var order = new Order { OrderId = 1007 };
            testDbContext.Order.Remove(order);
            testDbContext.SaveChanges();
        }

上面两种方式都会执行一条sql语句,在new 实体类中,主键属性被定义就行了。

 

关系表删除

仅当使用 EF Core 删除主体且将依赖实体加载到内存中(即对于跟踪的依赖项)时才应用 EF Core 模型中配置的删除行为。 需要在数据库中设置相应的级联行为以确保未由上下文跟踪的数据已应用必要的操作。 如果使用 EF Core 创建数据库,将为你设置此级联行为。

可选关系(就是外键值可以设置成null)

对于可选关系(可以为 null 的外键),可以保存 null 外键值,从而产生以下影响:

行为名称对内存中的依赖项/子项的影响对数据库中的依赖项/子项的影响
Cascade删除实体删除实体
ClientSetNull(默认)外键属性设置为 null
SetNull外键属性设置为 null外键属性设置为 null
Restrict

必选关系(就是外键值不可以设置成null)

对于必选关系(不可为 null 的外键),_不可以_保存 null 外键值,从而产生以下影响:

行为名称对内存中的依赖项/子项的影响对数据库中的依赖项/子项的影响
Cascade(默认)删除实体删除实体
ClientSetNullSaveChanges 引发异常
SetNull引发 SaveChanges引发 SaveChanges
Restrict

在上表中,“无” 可能会造成约束冲突。 例如,如果已删除主体/子实体,但不执行任何操作来更改依赖项/子项的外键,则由于发生外键约束冲突,数据库将可能会引发 SaveChanges。

高级别:

  • 如果实体在没有父项时不能存在,且希望 EF 负责自动删除子项,则使用“Cascade” 。
    • 在没有父项时不能存在的实体通常使用必选关系,其中“Cascade” 是默认值。
  • 如果实体可能有或可能没有父项,且希望 EF 负责为你将外键变为 null,则使用“ClientSetNull”
    • 在没有父项时可以存在的实体通常使用可选关系,其中“ClientSetNull” 是默认值。
    • 如果希望数据库即使在未加载子实体时也尝试将 null 值传播到子外键,则使用“SetNull” 。 但是,请注意,数据库必须支持此操作,并且如此配置数据库可能会导致其他限制,实际上这通常会使此选项不适用。 这就是SetNull不是默认值的原因。
  • 如果不希望 EF Core 始终自动删除实体或自动将外键变为 null,则使用“Restrict” 。 请注意,这要求使用代码手动同步子实体及其外键值,否则将引发约束异常。

不管EF CORE默认是什么,我们都可以手动修改默认值,如我的例子中,因为没有强加外键不可为空,所以默认的级联删除,会删除父类,而将子类的外键设置成null

也可以自定义属性

 protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
         
           modelBuilder.Entity<Order>().HasOne(f => f.User).WithMany(a => a.Orders).OnDelete(DeleteBehavior.Cascade);
           
        }

这样删除父类的时候会同时将子类删除掉

 public void DeleteRelation()
        {
            testDbContext.User.Remove(testDbContext.User.Include(a=>a.Orders).FirstOrDefault(t=>t.UserId==1007));
            testDbContext.SaveChanges();
        }
TestEFCore> Executed DbCommand (39ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
TestEFCore> SELECT TOP(1) [a].[UserId], [a].[DefaultCurrencyCode], [a].[FirstName], [a].[LastName], [a].[SecurityLevel]
TestEFCore> FROM [User] AS [a]
TestEFCore> WHERE [a].[UserId] = 1008
TestEFCore> ORDER BY [a].[UserId]
TestEFCore> 
TestEFCore> Executed DbCommand (4ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
TestEFCore> SELECT [a.Orders].[OrderId], [a.Orders].[Address], [a.Orders].[City], [a.Orders].[Country], [a.Orders].[Customer], [a.Orders].[OrderDate], [a.Orders].[Timestamp], [a.Orders].[UserId]
TestEFCore> FROM [Order] AS [a.Orders]
TestEFCore> INNER JOIN (
TestEFCore>     SELECT TOP(1) [a0].[UserId]
TestEFCore>     FROM [User] AS [a0]
TestEFCore>     WHERE [a0].[UserId] = 1008
TestEFCore>     ORDER BY [a0].[UserId]
TestEFCore> ) AS [t] ON [a.Orders].[UserId] = [t].[UserId]
TestEFCore> ORDER BY [t].[UserId]
TestEFCore> 
TestEFCore> Executed DbCommand (1ms) [Parameters=[@p0='?' (DbType = Int32), @p1='?' (Size = 8) (DbType = Binary)], CommandType='Text', CommandTimeout='30']
TestEFCore> SET NOCOUNT ON;
TestEFCore> DELETE FROM [Order]
TestEFCore> WHERE [OrderId] = @p0 AND [Timestamp] = @p1;
TestEFCore> SELECT @@ROWCOUNT;
TestEFCore> 
TestEFCore> Executed DbCommand (0ms) [Parameters=[@p2='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
TestEFCore> SET NOCOUNT ON;
TestEFCore> DELETE FROM [User]
TestEFCore> WHERE [UserId] = @p2;
TestEFCore> SELECT @@ROWCOUNT;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值