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

我目前使用:

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

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

还有其他选择吗?


当前回答

这里有几个问题,几乎所有的答案:

1]硬编码的sql。括号是否适用于所有数据库引擎? 2]实体框架Remove和RemoveRange调用。这会将所有实体加载到受操作影响的内存中。呵。 3]截表。与外键引用中断,可能无法跨所有数据库引擎工作。

使用https://entityframework-plus.net/,他们处理跨数据库平台的事情,将删除转换为正确的sql语句,并且不将实体加载到内存中,并且该库是免费的开源的。

免责声明:我不隶属于nuget包。他们确实提供了付费版本,功能甚至更多。

其他回答

对于那些像我一样在谷歌上搜索并最终来到这里的人来说,这是你目前在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}`;");
}
using (var context = new DataDb())
{
     var ctx = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext;
     ctx.ExecuteStoreCommand("DELETE FROM [TableName] WHERE Name= {0}", Name);
}

or

using (var context = new DataDb())
{
     context.Database.ExecuteSqlCommand("TRUNCATE TABLE [TableName]");
}

如果是MVC,你可以这样做:

public async Task<IActionResult> DeleteAll()
{
    var list = await _context.YourClass.ToListAsync();
    _context.YourClass.RemoveRange(list);
    await _context.SaveChangesAsync();
    return RedirectToAction(nameof(Index));
}

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

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

    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。

这在EF 5中正常工作:

YourEntityModel myEntities = new YourEntityModel();

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