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);
}
}
var objCtx = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)dataDb).ObjectContext;
objCtx.ExecuteStoreCommand("TRUNCATE TABLE [Table]");
8
var all = from c in dataDb.Table select c;
dataDb.Table.RemoveRange(all);
dataDb.SaveChanges();
37
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]");
}
1
这可以避免使用任何sql
using (var context = new MyDbContext())
{
var itemsToDelete = context.Set<MyTable>();
context.MyTables.RemoveRange(itemsToDelete);
context.SaveChanges();
}
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();
当然,如前所述,外键引用的表不能使用此解决方案(TRUNCATE失败) .
3
如果
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");
}
80
如果您希望清除整个数据库 .
由于外键约束,表格被截断的顺序很重要 . 这是一种强制执行此序列的方法 .
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 .
4
var data = (from n in db.users select n);
db.users.RemoveRange(data);
db.SaveChanges();
12 回答
对于那些谷歌搜索并最终像我一样的人,这就是你目前在EF5和EF6中的表现:
假设上下文是
System.Data.Entity.DbContext
Warning: 以下内容仅适用于小型表(想想<1000行)
这是一个使用实体框架(而不是SQL)来删除行的解决方案,因此它不是特定于SQL Engine(R / DBM)的 .
这假设您正在进行测试或类似情况 . 或
数据量很小或
表现并不重要
只需致电:
假设这个背景:
对于更整洁的代码,您可以声明以下扩展方法:
然后上面变成:
我最近使用这种方法为每个测试用例运行清理我的测试数据库(这显然比每次从头重新创建数据库更快,尽管我没有检查生成的删除命令的形式) .
Why can it be slow?
EF将获取所有行(VotingContext.Votes)
然后将使用他们的ID(不确定具体如何,无关紧要)来删除它们 .
因此,如果您正在处理大量数据,您将终止SQL服务器进程(它将消耗所有内存)和IIS进程相同的事情,因为EF将以与SQL服务器相同的方式缓存所有数据 . 如果您的表包含大量数据,请不要使用此项 .
使用SQL的TRUNCATE TABLE命令将是最快的,因为它在表上操作而不是在单个行上 .
假设
dataDb
是DbContext
(不是ObjectContext
),您可以将其包装并使用如下方法:要么
这可以避免使用任何sql
当我不得不处理一个特定的案例时,我遇到了这个问题:完全更新“叶子”表中的内容(没有指向它的FK) . 这涉及删除所有行并放置新行信息,它应该以事务方式完成(我不希望最终得到一个空表,如果插入因任何原因失败) .
我尝试了
public static void Clear<T>(this DbSet<T> dbSet)
方法,但没有插入新行 . 另一个缺点是整个过程很慢,因为行被逐个删除 .所以,我已经切换到
TRUNCATE
方法,因为它更快,它也是ROLLBACKable . 它也重置了身份 .使用存储库模式的示例
当然,如前所述,外键引用的表不能使用此解决方案(TRUNCATE失败) .
如果
原因
无法截断表'MyTable',因为它是由FOREIGN KEY约束引用的 .
我用这个:
如果您希望清除整个数据库 .
由于外键约束,表格被截断的顺序很重要 . 这是一种强制执行此序列的方法 .
用法:
记得在此之后重新实现你的DbContext .
没有Foreach,你可以做到这一点
这将删除所有行
这在EF 5中正常工作: