zoukankan      html  css  js  c++  java
  • Entity Framework Core系列教程-18-断开模式下删除数据

    Entity Framework Core 断开模式下删除数据

    EF Core API会为EntityState为Deleted的实体建立并执行数据库中的DELETE语句。在EF Core中已连接和已断开连接的场景中删除实体没有什么区别。 EF Core使得从上下文中删除实体变得容易,而上下文又将使用以下方法删除数据库中的记录。

    DbContext 方法 DbSet 方法 描述
    DbContext.Remove DbSet.Remove 将指定的实体附加到状态为“已删除”的DbContext并开始对其进行跟踪
    DbContext.RemoveRang DbSet.RemoveRange 将实体的集合或数组附加到具有Deleted状态的DbContext并开始跟踪它们

    以下示例演示了在断开连接的场景中删除实体的不同方法:

    // entity to be deleted
    var student = new Student() {
            StudentId = 1
    };
    
    using (var context = new SchoolContext()) 
    {
        context.Remove<Student>(student);
       
        // or the followings are also valid
        // context.RemoveRange(student);
        //context.Students.Remove(student);
        //context.Students.RemoveRange(student);
        //context.Attach<Student>(student).State = EntityState.Deleted;
        //context.Entry<Student>(student).State = EntityState.Deleted;
        
        context.SaveChanges();
    }
    

    在上面的示例中,使用Remove()或RemoveRange()方法从上下文中删除了具有有效StudentId的Studnet实体。数据将从SaveChanges()上的数据库中删除。上面的示例在数据库中执行以下delete命令:

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

    注意:EF Core中新引入了DbContext.Remove()和DbContext.RemoveRange()方法,以简化删除操作。

    异常

    如果相应数据库表中不存在Remove()或RemoveRange()方法中指定实体中的Key值,则EF Core将引发异常:以下示例将引发异常。

    var student = new Student() {
        StudentId = 50
    };
    
    using (var context = new SchoolContext()) {
        context.Remove<Student>(student);
        context.SaveChanges();
    }
    

    在上面的示例中,数据库中不存在StudentId = 50的Student。因此,EF Core将引发以下DbUpdateConcurrencyException:

    Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded.
    数据库操作预期会影响1行,但实际上会影响0行。自加载实体以来,数据可能已被修改或删除。
    

    因此,您需要适当地处理以上异常,或者在删除ID之前确保数据库中存在具有ID的对应数据。

    var student = new Student() {
        StudentId = 50
    };
    
    using (var context = new SchoolContext()) 
    {
        try
        {
            context.Remove<Student>(deleteStudent);
            context.SaveChanges();
        }    
        catch (DbUpdateConcurrencyException ex)
        {
            throw new Exception("数据库中不存在此纪录");
        }
        catch (Exception ex)
        {
            throw;
        }
    }
    

    删除多条记录

    您可以使用DbContext.RemoveRange()或DbSet.RemoveRange()方法一次性删除多个实体。

    IList<Student> students = new List<Student>() {
        new Student(){ StudentId = 1 },
        new Student(){ StudentId = 2 },
        new Student(){ StudentId = 3 },
        new Student(){ StudentId = 4 }
    };
    
    using (var context = new SchoolContext()) 
    {
        context.RemoveRange(students);
        
        // or
        // context.Students.RemoveRange(students);
        
        context.SaveChanges();
    }
    

    上面的示例将在单个数据库行程中从数据库中删除4条记录。因此,EF Core改善了性能。

    exec sp_executesql N'SET NOCOUNT ON;
    DELETE FROM [Students]
    WHERE [StudentId] = @p0;
    SELECT @@ROWCOUNT;
    
    
    DELETE FROM [Students]
    WHERE [StudentId] = @p1;
    SELECT @@ROWCOUNT;
    
    DELETE FROM [Students]
    WHERE [StudentId] = @p2;
    SELECT @@ROWCOUNT;
    
    
    DELETE FROM [Students]
    WHERE [StudentId] = @p3;
    SELECT @@ROWCOUNT;
    
    ',N'@p0 int,@p1 int',@p0=1,@p1=2,@p2=3,@p3=4
    go
    

    删除关联数据

    如果一个实体与其他实体有一对一或一对多的关系,则在删除根实体时删除相关数据取决于如何配置该关系。
    例如,考虑“学生”和“年级”实体之间存在一对多关系。特定的GradeId将有许多学生记录。如果我们尝试删除数据库中具有相关学生记录的成绩,EF将抛出参考完整性错误。要解决此问题,您可以使用Fluent API定义引用约束操作选项。例如,您可以为该关系配置一个级联删除选项,如下所示。

    modelBuilder.Entity<Student>()
        .HasOne<Grade>(s => s.Grade)
        .WithMany(g => g.Students)
        .HasForeignKey(s => s.GradeId)
        .OnDelete(DeleteBehavior.Cascade);
    

    现在,如果您删除成绩实体,那么所有相关的学生记录也将在数据库中删除。
    EF Core中还有其他引用约束操作选项,例如SetNull,ClientSetNull和Restrict。

  • 相关阅读:
    Python2 升级Python3
    'builtin_function_or_method' object has no attribute 'translate'
    antd-mobile的DatePicker分钟精度半小时
    Windows10远程报错:由于CredSSP加密Oracle修正
    Nginx配置
    MySQL之索引优化
    Ubuntu下删除VMware的方法
    控制窗体的显示和隐藏
    os模块
    树莓派 使用3.5耳机口输出音频
  • 原文地址:https://www.cnblogs.com/AlexanderZhao/p/12878806.html
Copyright © 2011-2022 走看看