实体框架。删除表中的所有行

新手上路,请多包涵

如何使用实体框架快速删除表中的所有行?

我目前正在使用:

 var rows = from o in dataDb.Table
           select o;
foreach (var row in rows)
{
    dataDb.Table.Remove(row);
}
dataDb.SaveChanges();

但是,执行需要很长时间。

有没有其他选择?

原文由 Zhenia 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 375
1 个回答

我的解决方案,混合了我的想法,一些答案(来自这个线程的 Ron 一个,还有 这个这个 用于反思)并试图涵盖一些不同的条件。

它基于 EF6,但应该可以正常工作,只需修复一些扩展,例如 GetTableName<TEntity>

我的解决方案:

  • 使用扩展,所以你只需要 DbSet 来启动
  • 有一个行计数阈值,在 RemoveRange 或 SQL 执行之间做出决定,以避免性能问题
  • SQL 版本基于 DELETE 而不是 TRUNCATE ,以避免外键问题(它必须符合您的要求,当然)
  • 有一个参数可以内联保存更改
private const int RangeLimit = 100;

private static void ClearTable<TEntity>(this DbSet<TEntity> dataSet, bool saveChanges = true) where TEntity : class
{
    DbContext context = null;

    if (dataSet.Count() > RangeLimit)
    {
        context = dataSet.GetContext();
        context.Database.ExecuteSqlCommand($"DELETE FROM [{context.GetTableName<TEntity>()}]");
    }
    else
    {
        dataSet.RemoveRange(dataSet);
    }

    if (!saveChanges)
    {
        return;
    }

    if (context == null)
    {
        context = dataSet.GetContext();
    }
    context.SaveChanges();
}

private static DbContext GetContext<TEntity>(this DbSet<TEntity> dbSet)
    where TEntity : class
{
    var internalSet = dbSet
        .GetType()
        .GetField("_internalSet", BindingFlags.NonPublic | BindingFlags.Instance)
        ?.GetValue(dbSet);
    var internalContext = internalSet?.GetType().BaseType
        ?.GetField("_internalContext", BindingFlags.NonPublic | BindingFlags.Instance)
        ?.GetValue(internalSet);
    return (DbContext)internalContext?.GetType()
        .GetProperty("Owner", BindingFlags.Instance | BindingFlags.Public)
        ?.GetValue(internalContext, null);
}

public static string GetTableName<TEntity>(this DbContext context) where TEntity : class
{
    return (context as IObjectContextAdapter).ObjectContext.CreateObjectSet<TEntity>().EntitySet.Name;
}

对于名为 Entries 的数据库表,您所要做的就是:

 databaseContext.Entries.ClearTable();

如果您想保存更改,或者您不想:

 databaseContext.Entries.ClearTable(false);

它基于反射,以简化代码。当然,它有一些性能折衷,但是每个表都会发生一次反射,因此在这些条件下应该是完全可以接受的。

原文由 buccia 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进