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

我目前使用:

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

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

还有其他选择吗?


当前回答

警告:以下仅适用于小表(考虑< 1000行)

这里是一个使用实体框架(而不是SQL)删除行的解决方案,因此它不是SQL Engine(R/DBM)特定的。

这里假设您这样做是为了测试或类似的情况。 要么

数据量过小或 表现不重要


简单地调用:

VotingContext.Votes.RemoveRange(VotingContext.Votes);

假设在此背景下:

public class VotingContext : DbContext
{
    public DbSet<Vote> Votes{get;set;}
    public DbSet<Poll> Polls{get;set;}
    public DbSet<Voter> Voters{get;set;}
    public DbSet<Candidacy> Candidates{get;set;}
}

为了让代码更整洁,你可以声明下面的扩展方法:

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

那么上面变成:

VotingContext.Votes.Clear();
VotingContext.Voters.Clear();
VotingContext.Candidacy.Clear();
VotingContext.Polls.Clear();
await VotingTestContext.SaveChangesAsync();

我最近使用这种方法为每次测试用例运行清理我的测试数据库(它显然比每次从头创建数据库快,尽管我没有检查生成的删除命令的形式)。


为什么会变慢?

EF将得到所有的行(VotingContext.Votes) 然后会使用他们的id(不知道具体怎么做,没关系)删除他们。

因此,如果你正在处理大量的数据,你将杀死SQL server进程(它将消耗所有的内存),同样的事情对于IIS进程,因为EF将缓存所有数据与SQL server相同的方式。如果您的表包含大量数据,请不要使用此方法。

其他回答

context.TableName.RemoveRange(context.TableName);
context.SaveChanges();

这在EF 5中正常工作:

YourEntityModel myEntities = new YourEntityModel();

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

使用SQL的TRUNCATE TABLE命令将是最快的,因为它操作的是表,而不是单个行。

dataDb.ExecuteStoreCommand("TRUNCATE TABLE [Table]");

假设dataDb是一个DbContext(而不是ObjectContext),你可以包装它并像这样使用方法:

var objCtx = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)dataDb).ObjectContext;
objCtx.ExecuteStoreCommand("TRUNCATE TABLE [Table]");

确保当你试图删除父级时,所有的子级将在删除时级联。或者子节点的外键为空。

这避免了使用任何sql

using (var context = new MyDbContext())
{
    var itemsToDelete = context.Set<MyTable>();
    context.MyTables.RemoveRange(itemsToDelete);
    context.SaveChanges();
}