87

使用 Entity Framework 4.3 删除 System.Data.Entity.DbSet 中所有元素的最佳方法是什么?

4

7 回答 7

111
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();

但是在这两种情况下,您都必须加载所有实体或所有关键属性,并从集合中一个一个地删除实体。此外,当您调用SaveChangesEF 时,会将 n(=集合中的实体数)DELETE 语句发送到数据库,这些语句也会在数据库中一一执行(在单个事务中)。

因此,直接 SQL 显然更适合此目的,因为您只需要一个 DELETE 语句。

于 2012-05-04T14:32:42.680 回答
55

旧帖子,但现在有一个 RemoveRange 方法:

    dbContext.MyEntities.RemoveRange(dbContext.MyEntities);
    dbContext.SaveChanges();
于 2018-05-16T07:53:26.893 回答
18

这是您可以在代码中执行此操作的另一种方式。

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>();
于 2013-10-01T17:10:19.397 回答
3

如果您想在不编写任何 SQL的情况下删除所有元素并且只执行Single Db Call

实体框架扩展库提供了批量删除方法。

context.Users.Delete();
于 2016-02-16T11:12:44.863 回答
2

由于接受的答案仅提及以下方法:

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()
于 2016-08-30T11:40:55.857 回答
1

如果您正在使用工作单元和通用存储库,您可能会发现以下有用

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();
于 2015-02-22T00:30:46.223 回答
-1

使用存储库模式,您可以在其中为存储库提供模型的类型,它可以在任何模型类型上工作。

    public async Task<int> RemoveAllAsync()
    {
        Context.Set<T>().RemoveRange(await Context.Set<T>().ToListAsync());
        return await Context.SaveChangesAsync();
    }
于 2021-05-03T20:35:32.873 回答