C# 如何删除数据库集中的所有元素?
使用Entity Framework 4.3删除System.Data.Entity.DbSet中所有元素的最佳方法是什么C# 如何删除数据库集中的所有元素?,c#,.net,entity-framework-4,C#,.net,Entity Framework 4,使用Entity Framework 4.3删除System.Data.Entity.DbSet中所有元素的最佳方法是什么 dbContext.Database.ExecuteSqlCommand("delete from MyTable"); (不是开玩笑。) 问题在于,EF不支持任何批处理命令,使用直接DML删除集合中所有实体的唯一方法是: foreach (var entity in dbContext.MyEntities) dbContext.MyEntities.Remov
dbContext.Database.ExecuteSqlCommand("delete from MyTable");
(不是开玩笑。)
问题在于,EF不支持任何批处理命令,使用直接DML删除集合中所有实体的唯一方法是:
foreach (var entity in dbContext.MyEntities)
dbContext.MyEntities.Remove(entity);
dbContext.SaveChanges();
或者,为了避免加载完整实体,可能会稍微便宜一点:
foreach (var id in dbContext.MyEntities.Select(e => e.Id))
{
var entity = new MyEntity { Id = id };
dbContext.MyEntities.Attach(entity);
dbContext.MyEntities.Remove(entity);
}
dbContext.SaveChanges();
但在这两种情况下,您都必须加载所有实体或所有关键属性,并从集合中逐个删除实体。此外,当您调用SaveChanges
EF时,它将向数据库发送n(=集合中的实体数)条DELETE语句,这些语句也会在数据库中逐个执行(在单个事务中)
因此,直接SQL显然更适合用于此目的,因为您只需要一条DELETE语句。下面是另一种可以在代码中执行的方法
public static class Extensions
{
public static void DeleteAll<T>(this DbContext context)
where T : class
{
foreach (var p in context.Set<T>())
{
context.Entry(p).State = EntityState.Deleted;
}
}
}
公共静态类扩展
{
公共静态void DeleteAll(此DbContext上下文)
T:在哪里上课
{
foreach(context.Set()中的var p)
{
context.Entry(p).State=EntityState.Deleted;
}
}
}
要实际调用该方法并清除集合,请执行以下操作:
myDbContext.DeleteAll<MyPocoClassName>();
myDbContext.DeleteAll();
如果您使用的是工作单元和通用存储库,您可能会发现以下内容很有用
public virtual void DeleteWhere(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
foreach (var entity in query)
{
context.Entry(entity).State = EntityState.Deleted;
}
}
如果要删除所有元素而不写入任何SQL,并且只执行单个Db调用 提供批删除方法
context.Users.Delete();
由于公认的答案仅提及以下方法:
context.Database.ExecuteSqlCommand("delete from MyTable");
我已经设法编写了一个方法,您可以使用它来避免加载所有实体,然后在它们之间循环并使用ExecuteSqlCommand
假设使用工作单元,其中context是DbContext:
using System.Data.Entity.Core.Objects;
using System.Text.RegularExpressions;
public void DeleteAll()
{
ObjectContext objectContext = ( (IObjectContextAdapter)context ).ObjectContext;
string sql = objectContext.CreateObjectSet<T>().ToTraceString();
Regex regex = new Regex( "FROM (?<table>.*) AS" );
Match match = regex.Match( sql );
string tableName = match.Groups[ "table" ].Value;
context.Database.ExecuteSqlCommand( string.Format( "delete from {0}", tableName ) );
}
没有必要打电话
context.SaveChanges()
旧帖子,但现在有一个Removate方法:
dbContext.MyEntities.RemoveRange(dbContext.MyEntities);
dbContext.SaveChanges();
使用repository模式,您可以向存储库提供模型的类型,并且它可以处理任何模型类型
public async Task<int> RemoveAllAsync()
{
Context.Set<T>().RemoveRange(await Context.Set<T>().ToListAsync());
return await Context.SaveChangesAsync();
}
public异步任务RemoveAllAsync()
{
Context.Set().RemoveRange(等待Context.Set().ToListAsync());
返回wait Context.SaveChangesAsync();
}
是否需要在dbContext.Database.ExecuteSqlCommand
之后调用SaveChanges
?真正的问题是dbContext如何提供对其所有数据库集/实体的访问?除非使用反射,否则无法在其上循环。这就是你在提到“MyEntities”时想到的吗?用Remove
代替Remove
怎么样?你会说,我使用这个答案是因为代码简单明了。我相信有更有效的方法可以做到这一点,但我使用的是一个将在一夜之间运行的Azure WebJob,因此这一点不值得关注。RemoveRange的问题是,您仍然必须从DB(或至少是IDs)查询所有实体,因为此方法只是foreach的包装器。
dbContext.MyEntities.RemoveRange(dbContext.MyEntities);
dbContext.SaveChanges();
public async Task<int> RemoveAllAsync()
{
Context.Set<T>().RemoveRange(await Context.Set<T>().ToListAsync());
return await Context.SaveChangesAsync();
}