C# 如何删除数据库集中的所有元素?

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

使用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语句。

下面是另一种可以在代码中执行的方法

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