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)。
为什么它会变慢?
- EF会得到所有的行(VotingContext.Votes)
- 然后将使用他们的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]");