删除entity framework中的所有实体

我想删除所有表(所有实体)使用entity framework4 +的内容。 如何才能做到这一点?

这比执行删除单个实体对象的任何事情都要好得多,假设底层数据库是MSSQL。

foreach (var tableName in listOfTableNames) { context.ExecuteStoreCommand("TRUNCATE TABLE [" + tableName + "]"); } 

当然,如果你的表有外键关系,你需要按照正确的顺序设置你的表名列表,这样在清除它们可能依赖的主键表之前,你可以清除外键表。

对于懒惰的代码,当我寻找答案时,我自己find了代码:

 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) { context.Database.ExecuteSqlCommand(string.Format("DELETE FROM {0}", tableName)); } context.SaveChanges(); } } 

简单的解释:由于缺乏权限,我不会截断表,如果这对您没有问题,请随时这样做。 where语句忽略表__MigrationHistory。

更新:经过一些研究,我想出了更好的解决scheme(不是很好,但只删除所需的列):

 public static void ClearDatabase(DbContext context) { var objectContext = ((IObjectContextAdapter)context).ObjectContext; var entities = objectContext.MetadataWorkspace.GetEntityContainer(objectContext.DefaultContainerName, DataSpace.CSpace).BaseEntitySets; var method = objectContext.GetType().GetMethods().First(x => x.Name == "CreateObjectSet"); var objectSets = entities.Select(x => method.MakeGenericMethod(Type.GetType(x.ElementType.FullName))).Select(x => x.Invoke(objectContext, null)); var tableNames = objectSets.Select(objectSet => (objectSet.GetType().GetProperty("EntitySet").GetValue(objectSet, null) as EntitySet).Name).ToList(); foreach (var tableName in tableNames) { context.Database.ExecuteSqlCommand(string.Format("DELETE FROM {0}", tableName)); } context.SaveChanges(); } 

对于EF 6:

 DbSet<Entity>.RemoveRange(DbSet<Entity>); 

使用如下代码遍历表:

 context.GetType().GetProperties() .Where(propertyInfo => propertyInfo.PropertyType == typeof(Table<>)) .Select(propertyInfo => propertyInfo.GetValue(context, null) as ITable).ToList() .Foreach(table => { //code that deletes the actual tables records. } ); 

我想尝试改进@Wojciech Markowski的伟大答案。

如果你像我一样懒,也不想检查外键约束,可以使用这个方法:

  private void ClearDatabase(TContext context) { // disable all foreign keys //context.Database.ExecuteSqlCommand("EXEC sp_MSforeachtable @command1 = 'ALTER TABLE ? NOCHECK CONSTRAINT all'"); List<string> tableNames = context.Database.SqlQuery<string>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME NOT LIKE '%Migration%'").ToList(); for (int i = 0; tableNames.Count>0; i++) { try { context.Database.ExecuteSqlCommand(string.Format("DELETE FROM {0}", tableNames.ElementAt(i % tableNames.Count))); tableNames.RemoveAt(i % tableNames.Count); i = 0; } catch { } // ignore errors as these are expected due to linked foreign key data } context.SaveChanges(); } 

ClearDatabase方法遍历表的清单并清理它们。 如果findFK约束,则捕获exception并转到下一个表。 最后所有的表格都将被删除。

而且,如果你不介意松开所有的FK限制,你可以通过下面的命令禁用所有的限制:

 context.Database.ExecuteSqlCommand("EXEC sp_MSforeachtable @command1 = 'ALTER TABLE ? NOCHECK CONSTRAINT all'"); 

还有一件事:如果你想删除所有的表格,而不是只清除它们,那么更换这行:

 context.Database.ExecuteSqlCommand(string.Format("DELETE FROM {0}", tableNames.ElementAt(i % tableNames.Count))); 

有:

 context.Database.ExecuteSqlCommand(string.Format("DROP TABLE {0}", tableNames.ElementAt(i % tableNames.Count))); 

我亲自在代码优先的迁移中检查了Entity Framework 6上的这个答案。

编辑:更好的版本:

  private void ClearDatabase(MrSaleDbContext context) { //Optional: disable all foreign keys (db-schema will be loosed). //context.Database.ExecuteSqlCommand("EXEC sp_MSforeachtable @command1 = 'ALTER TABLE ? NOCHECK CONSTRAINT all'"); List<string> tableNames = context.Database.SqlQuery<string>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME NOT LIKE '%Migration%' AND TABLE_NAME NOT LIKE 'AspNet%'").ToList(); for (int i = 0; tableNames.Count > 0; i++) { try { //To delete all tables and not just clean them from data, replace "DELETE FROM {0}" in "DROP TABLE {0}": context.Database.ExecuteSqlCommand(string.Format("DELETE FROM {0}", tableNames.ElementAt(i % tableNames.Count))); tableNames.RemoveAt(i % tableNames.Count); i = -1; //flag: a table was removed. in the next iteration i++ will be the 0 index. } catch (System.Data.SqlClient.SqlException e) // ignore errors as these are expected due to linked foreign key data { if ((i % tableNames.Count) == (tableNames.Count - 1)) { //end of tables-list without any success to delete any table, then exit with exception: throw new System.Data.DataException("Unable to clear all relevant tables in database (foriegn key constraint ?). See inner-exception for more details.", e); } } } 

catch块中的if语句检查我是否到达表列表的最后一个索引而不删除任何表。 在这种情况下,不要进入无限循环,而是抛出exception并退出for。

截断不能在外键内删除。

然后我做了DbContext的扩展方法。

用法很简单。

db.Truncates(); //所有表删除。

db.Truncates(“Test1”,“Test2”); //只有“Test1,Test2”表删除

 public static class DbContextExtension { public static int Truncates(this DbContext db, params string[] tables) { List<string> target = new List<string>(); int result = 0; if (tables == null || tables.Length == 0) { target = db.GetTableList(); } else { target.AddRange(tables); } using (TransactionScope scope = new TransactionScope()) { foreach (var table in target) { result += db.Database.ExecuteSqlCommand(string.Format("DELETE FROM [{0}]", table)); db.Database.ExecuteSqlCommand(string.Format("DBCC CHECKIDENT ([{0}], RESEED, 0)", table)); } scope.Complete(); } return result; } public static List<string> GetTableList(this DbContext db) { var type = db.GetType(); return db.GetType().GetProperties() .Where(x => x.PropertyType.Name == "DbSet`1") .Select(x => x.Name).ToList(); } }