entity framework。 删除表中的所有行

我如何使用Entity Framework快速删除表中的所有行?

我目前使用:

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

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

有没有其他的select?

对于那些使用googling并最终在我这里结束的人来说,这就是你目前在EF5和EF6中的做法:

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

假设上下文是一个System.Data.Entity.DbContext

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

这是一个使用entity framework(而不是SQL)删除行的解决scheme,因此它不是SQL引擎(R / DBM)特定的。

这假设你正在做这个testing或类似的情况。 或

  • 数据量很小
  • 表演并不重要

只需致电:

 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(); 

我最近使用这种方法来清理每个testing用例运行的testing数据库(这显然比每次从头重新创build数据库要快,尽pipe我没有检查生成的删除命令的forms)。


为什么它会变慢?

  1. EF会得到所有的行(VotingContext.Votes)
  2. 然后将使用他们的ID(不知道如何,无所谓),删除它们。

所以,如果你使用的是大量的数据,那么你将会终止SQL服务器进程(它将消耗所有的内存),并为IIS进程做同样的事情,因为EF会像SQL服务器一样caching所有的数据。 如果你的表包含大量的数据,不要使用这个。

干杯! ;)

使用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]"); 
 var all = from c in dataDb.Table select c; dataDb.Table.RemoveRange(all); dataDb.SaveChanges(); 
 using (var context = new DataDb()) { var ctx = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext; ctx.ExecuteStoreCommand("DELETE FROM [TableName] WHERE Name= {0}", Name); } 

要么

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

这避免了使用任何SQL

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

像Rudi Visser写道:

使用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]”);

但是你必须确保在任何地方使用新创build的数据上下文,否则你会得到entity framework冲突。 在datacontext里面,这些实体在使用Truncate table的时候还是活着的。

如果

  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"); } 

当我必须处理一个特定的情况时,我遇到了这个问题:完全更新“叶”表中的内容(没有FK指向它)。 这涉及到删除所有行和放置新的行信息,它应该事务性地完成(我不想结束一个空表,如果插入失败,无论出于何种原因)。

我已经尝试了public static void Clear<T>(this DbSet<T> dbSet)方法,但新行不插入。 另一个缺点是整个过程很慢,因为行被逐个删除。

所以,我已经切换到TRUNCATE方法,因为它更快,它也是ROLLBACKable 。 它也重置身份。

使用存储库模式的示例

 public class Repository<T> : IRepository<T> where T : class, new() { private readonly IEfDbContext _context; public void BulkInsert(IEnumerable<T> entities) { _context.BulkInsert(entities); } public void Truncate() { _context.Database.ExecuteSqlCommand($"TRUNCATE TABLE {typeof(T).Name}"); } } // usage DataAccess.TheRepository.Truncate(); var toAddBulk = new List<EnvironmentXImportingSystem>(); // fill toAddBulk from source system // ... DataAccess.TheRepository.BulkInsert(toAddBulk); DataAccess.SaveChanges(); 

当然,正如已经提到的,这个解决scheme不能被外键引用的表使用(TRUNCATE失败)。

如果你想清除整个数据库。

由于外键约束,表格被截断的顺序很重要。 这是强制这个顺序的一种方式。

  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。

 var data = (from n in db.users select n); db.users.RemoveRange(data); db.SaveChanges(); 

这适用于EF 5:

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