如何在Entity Framework 4.3中最好地删除System.Data.Entity.DbSet中的所有元素?
如何在Entity Framework 4.3中最好地删除System.Data.Entity.DbSet中的所有元素?
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 语句。
虽然这是一篇旧文章,但现在有一个RemoveRange方法:
dbContext.MyEntities.RemoveRange(dbContext.MyEntities);
dbContext.SaveChanges();
以下是您可以在代码中使用的另一种方法。
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;
}
}
}
要实际调用方法并清除集合:
myDbContext.DeleteAll<MyPocoClassName>();
context.Users.Delete();
context.SaveChanges()
吗?如果不需要的话,我会认为扩展库中的 Delete()
方法是在上一次调用 context.SaveChanges()
之后发生在一个独立的事务中的,与其他数据库更改无关。 - J.D.context.Database.ExecuteSqlCommand("delete from MyTable");
相反地,我已经编写了一种方法,可以避免加载所有实体,然后通过循环使用ExecuteSqlCommand,而不是直接加载所有实体。
假设使用工作单元,在其中上下文是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 ) );
}
第一个代码块检索在ExecuteSqlCommand方法中所需的表格名称。
using ( var context = new UnitOfWork() )
{
context.MyRepository.DeleteAll();
}
不需要打电话
了解
context.SaveChanges()
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;
}
}
使用方法:
uow.myRepositoryName.DeleteWhere(u => u.RoomId == roomId);
uow.Save();
public async Task<int> RemoveAllAsync()
{
Context.Set<T>().RemoveRange(await Context.Set<T>().ToListAsync());
return await Context.SaveChangesAsync();
}
dbContext.Database.ExecuteSqlCommand
后,您需要调用SaveChanges
吗? - PeterXRemoveRange
代替Remove
怎么样?你会说,“这只是在 EF 6 中引入的,而 OP 问的是关于 EF 4.* 的”吗? - Nate Anderson