【问题标题】:Truncate table in entity framework core实体框架核心中的截断表
【发布时间】:2021-05-16 03:42:34
【问题描述】:

如何使用 C# 代码而不是 SQL 查询截断某个表?

我想要相当于TRUNCATE TABLE <table_name>

到目前为止,我已经尝试过:

context.Products.RemoveRange(context.Products);

但是,它什么也没做

【问题讨论】:

  • EF 无法做到这一点。但是,您可以在上下文中使用 SQL 查询,例如 context.Database.ExecuteSqlRaw("Truncate table <table_name>");
  • 顺便说一句,RemoveRange 应该可以工作(但它不会截断表格,它会为每个匹配的行使用delete),之后您是否使用了context.SaveChanges()
  • @Magnetron 你是对的......我完全忘记了保存更改。现在可以了!

标签: c# sql entity-framework entity-framework-core


【解决方案1】:

我为 EF Core 5.0.11 做了如下的事情 这适用于 SQL Server、Oracle、PostgreSQL

public class AnnotationHelper
{
    /*
     * https://stackoverflow.com/questions/45667126/how-to-get-table-name-of-mapped-entity-in-entity-framework-core
     */
    private static string GetName(IEntityType entityType, string defaultSchemaName = "dbo")
    {
        //var schemaName = entityType.GetSchema();
        //var tableName = entityType.GetTableName();
        var schema = entityType.FindAnnotation("Relational:Schema").Value;
        string tableName = entityType.GetAnnotation("Relational:TableName").Value.ToString();
        string schemaName = schema == null ? defaultSchemaName : schema.ToString();
        string name = string.Format("[{0}].[{1}]", schemaName, tableName);
        return name;

    }

    public static string TableName<T>(DbSet<T> dbSet) where T : class
    {
        var entityType = dbSet.EntityType;
        return GetName(entityType);
    }
}
 

public static class EfHelper
{
    /*
     * need to install Microsoft.EntityFrameworkCore.Relational
     */
    public static string Truncate<T>(this DbSet<T> dbSet) where T : class
    {
        var context = dbSet.GetService<ICurrentDbContext>().Context;
        string cmd = $"TRUNCATE TABLE {AnnotationHelper.TableName(dbSet)}";        
        using (var command = context.Database.GetDbConnection().CreateCommand())
        {
            if (command.Connection.State != ConnectionState.Open)
            {
                command.Connection.Open();
            }
            command.CommandText = cmd;
            command.ExecuteNonQuery();
        }
        return cmd;
    }
}


[Test]
public void Truncate()
{
    Db.Users.Add(new User() 
    {
        Name = "Name",
        Email = "Email",
        CreatedBy = "CreatedBy",
        CreatedOn = DateTime.Now
    });
    Db.SaveChanges();
    Assert.GreaterOrEqual(Db.Users.ToList().Count, 1);

    /*Truncate table*/
    Db.Users.Truncate();
    Assert.AreEqual(0, Db.Users.ToList().Count);
}

【讨论】:

    【解决方案2】:

    re: CodeCaster 提到的扩展:如果你被允许在你的代码中使用 NUGET 包,你可能会发现这个库很有用;与您所询问的完全一样,它具有“Truncate”和“TruncateAsync”。

    https://github.com/borisdj/EFCore.BulkExtensions

    是的,在幕后它仍在使用“ExecuteSqlRaw”,但使用 c# 方法可以更好地处理错误。例如,在某些情况下,数据库安全性可能不允许执行线程截断表,因此如果这对您的应用程序很重要,您可以使用包装器更轻松地处理它。

    【讨论】:

    • 那 nuget 付钱了吗?我们可以在不付费的情况下使用 truncate 吗?
    【解决方案3】:

    你不能,这不是 ORM 的用途。

    ORM 可帮助您在对象访问方面访问数据库。截断表是数据层操作,而不是对象操作。 Entity Framework 中的等价物是从数据库中加载所有对象并一一删除。

    您不希望这样,您想截断表格。然后深入研究 SQL 并截断该表。

    当然,实体框架上的扩展允许这样的事情,但最终它们会生成您阻止执行的 SQL,那么为什么不简单地自己做呢?

    【讨论】:

    • 谢谢。只是想知道我是否错过了文档中的某些内容。然后我将使用 ExecuteSqlRaw 来满足这些需求。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 2020-05-10
    • 2020-09-12
    • 2020-06-21
    相关资源
    最近更新 更多