在Entity Framework Core 5中删除表中的所有行

目录

背景

扩展助手

先决条件 

表名

Delete/Truncate/Clear

使用代码

数据库上下文

删除

Truncate

清除

限制

参考


背景

有时我们可能需要使用Entity Framework Core从表中删除所有记录。一种常用的方法是迭代每一行并使用DBSet.Remove()

foreach (var item in Db.Users)
{
    Db.Users.Remove(item);
}
Db.SaveChanges();

在这篇文章中,我们将探索一些替代方案。

扩展助手

先决条件 

需要安装NuGet Microsoft.EntityFrameworkCore.Relational

install Microsoft.EntityFrameworkCore.Relational

表名

获取映射实体的表名和模式的扩展方法。我们将使用这个名称和模式来创建一个Truncate/Delete脚本。

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;

public class AnnotationHelper
{
    private static string GetName(IEntityType entityType, string defaultSchemaName = "dbo")
    {
        /*3.0.1 these were working*/
        //var schemaName = entityType.GetSchema();
        //var tableName = entityType.GetTableName();
        
        var schema = entityType.FindAnnotation("Relational:Schema").Value;
        string tableName = entityType.GetAnnotation("Relational:TableName").Value.ToString();
        string schemaName = schema == null ? defaultSchemaName : schema.ToString();
        string name = string.Format("[{0}].[{1}]", schemaName, tableName);
        return name;
    }

    public static string TableName<T>(DbContext dbContext) where T : class
    {
        var entityType = dbContext.Model.FindEntityType(typeof(T));
        return GetName(entityType);
    }

    public static string TableName<T>(DbSet<T> dbSet) where T : class
    {
        var entityType = dbSet.EntityType;
        return GetName(entityType);
    }
}

Delete/Truncate/Clear

 DbSet<T> 对象的扩展方法

  • string Truncate<T>(this DbSet<T> dbSet)使用截断查询截断表
  • string Delete<T>(this DbSet<T> dbSet)使用删除查询删除表的所有行
  • void Clear<T>(this DbSet<T> dbSet)使用RemoveRange方法删除表的所有行

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using System.Data;
using System.Linq;

public static class EfHelper
{
    public static string Truncate<T>(this DbSet<T> dbSet) where T : class
    {
        string cmd = $"TRUNCATE TABLE {AnnotationHelper.TableName(dbSet)}";
        var context = dbSet.GetService<ICurrentDbContext>().Context;
        context.Database.ExecuteSqlRaw(cmd);
        return cmd;
    }

    public static string Delete<T>(this DbSet<T> dbSet) where T : class
    {
        string cmd = $"DELETE FROM {AnnotationHelper.TableName(dbSet)}";
        var context = dbSet.GetService<ICurrentDbContext>().Context;
        context.Database.ExecuteSqlRaw(cmd);
        return cmd;
    }

    public static void Clear<T>(this DbSet<T> dbSet) where T : class
    {
        if (dbSet.Any())
        {
            dbSet.RemoveRange(dbSet.ToList());
        }
    }
}

使用代码

数据库上下文

我们当前的数据库上下文类。

public class AppDbContext : DbContext
{
    public DbSet<User> Users { get; set; }
}

删除

Db.Users.Delete();

与数据库事务一起使用

string errorMsg = "Error";
User newUser = null;
Exception exception = null;
using (var tran = Db.Database.BeginTransaction())
{
    try
    {
        newUser = new User()
        {
            Name = "Name",
            Email = "Email",
            CreatedBy = "CreatedBy",
            CreatedOn = DateTime.Now
        };
        Db.Users.Add(newUser);
        Db.SaveChanges();

        Db.Users.Delete();

        throw new Exception(errorMsg);

        tran.Commit();
    }
    catch (Exception ex)
    {
        exception = ex;
        tran.Rollback();
    }
}

Truncate

Db.Users.Truncate();

清除

Db.Users.Clear();
Db.SaveChanges();

限制

  • Delete()Truncate() SQL语句立即执行,不管我们是否调用Db.SaveChanges()
  • 我们将无法进行单元测试Delete() Truncate()
  • Clear()对于大型数据集来说速度很慢,但可以进行单元测试。
  • 使用SQL ServerOracle测试的代码。

参考

https://www.codeproject.com/Tips/5320939/Delete-All-Rows-in-a-Table-in-Entity-Framework-Cor

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值