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

我目前使用:

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

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

还有其他选择吗?


当前回答

If

using(var db = new MyDbContext())
{
    await db.Database.ExecuteSqlCommandAsync(@"TRUNCATE TABLE MyTable"););
}

原因

不能截断表'MyTable',因为它正被一个FOREIGN KEY约束引用。

我用这个:

using(var db = new MyDbContext())
{
    await db.Database.ExecuteSqlCommandAsync(@"DELETE FROM MyTable WHERE ID != -1");
}

其他回答

这在EF 5中正常工作:

YourEntityModel myEntities = new YourEntityModel();

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

没有Foreach你也能做到

dataDB.Table.RemoveRange(dataDB.Table);
dataDB.SaveChanges();

这将删除所有行

工作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是一个扩展

对于那些像我一样在谷歌上搜索并最终来到这里的人来说,这是你目前在EF5和EF6中所做的:

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

假设context是System.Data.Entity.DbContext

编辑:

目前在net6.0 (dotnet 6核心)你可以做以下事情:

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

或者使用Async重载:

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

这些是来自Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions的扩展方法

如果你有外键的问题(在MySql中),你可能不得不做以下事情(执行SET FOREIGN_KEY_CHECKS = 0;单独打电话的部分似乎对我不起作用)

context.Database.ExecuteSqlRaw("SET FOREIGN_KEY_CHECKS = 0; TRUNCATE TABLE [TableName];");

所以如果你想要截断你的整个数据库(可能是单元测试的原因),你可以这样做:

var tableNames = context.Model.GetEntityTypes()
    .Select(t => t.GetTableName())
    .Distinct()
    .ToList();

foreach (var tableName in tableNames)
{
    context.Database.ExecuteSqlRaw($"SET FOREIGN_KEY_CHECKS = 0; TRUNCATE TABLE `{tableName}`;");
}

EF Core 7.0通过添加批量更新和删除语义一次性解决了这个问题:

await dataDB.Table.ExecuteDeleteAsync();

注意,此语法立即执行底层(SQL)命令从表中删除数据。它不需要跟踪实体、标记实体以便删除,也不需要等待UpdateDatabase对数据库执行事务。

还要注意,默认情况下,单个事务中不会包含多个ExecuteDelete和ExecuteUpdate命令。但是,可以使用DbContext事务api在事务中包装这些命令。