我如何才能快速删除使用实体框架表中的所有行?

我目前使用:

var rows = from o in dataDb.Table
           select o;
foreach (var row in rows)
{
    dataDb.Table.Remove(row);
}
dataDb.SaveChanges();

但是,执行起来需要很长时间。

还有其他选择吗?


当前回答

在EFCore(我使用的版本是3.1),你可以使用以下方法删除所有行-

context.Database.ExecuteSqlRaw("TRUNCATE TABLE [TableName]");

其他回答

删除所有记录。不要像“truncate”那样重置主索引。

/// <summary>
/// SET - DELETE all record by table - no truncate - return deleted records
/// </summary>
public static int setListDelAllMYTABLE()
{
    // INIT
    int retObj = 0;
    using (MYDBEntities ctx = new MYDBEntities())
    {
        // GET - all record
        var tempAllRecord = ctx.MYTABLE.ToList();
        // RESET
        ctx.MYTABLE.RemoveRange(tempAllRecord);
        // SET - final save
        retObj += ctx.SaveChanges();
    }
    // RET
    return retObj;
}

工作EF核心3

public static class EntityExtensions
{
    public static async Task ClearAsync<T>(this DbSet<T> dbSet) where T : class
    {
        var command = dbSet.CreateDbCommand();
        command.CommandText = $"TRUNCATE TABLE {dbSet.EntityType.GetSchema()}.{dbSet.EntityType.GetTableName()}";
        await command.ExecuteNonQueryAsync();
    }
}

但是请注意dbSet。CreateDbCommand是一个扩展

这在EF 5中正常工作:

YourEntityModel myEntities = new YourEntityModel();

var objCtx = ((IObjectContextAdapter)myEntities).ObjectContext;
objCtx.ExecuteStoreCommand("TRUNCATE TABLE [TableName]");

如果您希望清除整个数据库。

由于外键的限制,截断表的顺序很重要。这是一种强行执行这个序列的方法。

    public static void ClearDatabase<T>() where T : DbContext, new()
    {
        using (var context = new T())
        {
            var tableNames = context.Database.SqlQuery<string>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME NOT LIKE '%Migration%'").ToList();
            foreach (var tableName in tableNames)
            {
                foreach (var t in tableNames)
                {
                    try
                    {

                        if (context.Database.ExecuteSqlCommand(string.Format("TRUNCATE TABLE [{0}]", tableName)) == 1)
                            break;

                    }
                    catch (Exception ex)
                    {

                    }
                }
            }

            context.SaveChanges();
        }
    }

用法:

ClearDatabase<ApplicationDbContext>();

记住在此之后重新实例化DbContext。

下面是Ron的流行解决方案的一个变体,它通过利用另一个关于堆栈溢出的流行解决方案来确定实体框架类的底层表名,从而避免使用硬编码的字符串表名。

使用这些扩展方法,解决方案看起来像这样:

_dbContext.TruncateTable<TheTableName>();

(使用this.TruncateTable <…如果你在EF DBContext类或部分类文件中编辑代码)

这是扩展类:

public static class EntityFrameworkExtensions
{
    private static string ParseTableNameFromSQL(string sql)
    {
        Regex regex = new Regex("FROM (?<table>.*) AS");
        Match match = regex.Match(sql);

        string table = match.Groups["table"].Value;
        return table;
    }
    
    public static string GetTableName<T>(this IObjectContextAdapter context) where T : class =>
        ParseTableNameFromSQL(context.ObjectContext.CreateObjectSet<T>().ToTraceString());
    
    public static void TruncateTable<T>(this DbContext dbContext) where T : class =>
        dbContext.Database.ExecuteSqlCommand($"TRUNCATE TABLE {dbContext.GetTableName<T>()}");

    public static void DeleteAllTableRows<T>(this DbContext dbContext) where T : class =>
        dbContext.Database.ExecuteSqlCommand($"DELETE FROM {dbContext.GetTableName<T>()}");
}

最后一个扩展方法DeleteAllTableRows是一个有用的替代方案,如果你的表不能被截断(例如,由于外键引用)-这仍然比实体框架RemoveAll替代方案快得多。