实体框架核心中的截断表

Posted

技术标签:

【中文标题】实体框架核心中的截断表【英文标题】: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 你是对的......我完全忘记了保存更改。现在可以了! 【参考方案1】:

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

public class AnnotationHelper

    /*
     * https://***.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 来满足这些需求。谢谢!

以上是关于实体框架核心中的截断表的主要内容,如果未能解决你的问题,请参考以下文章

postgresql jsonb的实体框架核心中的等效数据类型

在实体框架核心中获取最新记录

实体框架代码首先截断我的小数

为啥实体框架在保存到数据库时会截断字符串值?

实体框架核心错误? SaveChanges 抛出选择

如何使用 .net 核心实体框架迁移更新表(而不是重新创建它们)