在 EF Core 中使用计算的 IsDeleted 列进行软删除,无需手动使用 SQL 语句

Soft Delete with computed IsDeleted column in EF Core, without manually using SQL statement

提问人:Amin 提问时间:11/2/2023 更新时间:11/2/2023 访问量:70

问:

我有一个模型,其中包含一个属性。我想为它实现软删除。我可以简单地用来检查它是否为 null。 问题是:我想知道,是否有某种方法可以在模型中有一个计算字段,该字段未映射到数据库中的任何列。但它是通过检查 的值来评估的。 我尝试的是在模型中定义这样的属性:DeleteTimeDeleteTimeIsDeletedDeleteTime

public bool IsDeleted { get { return DeleteTime != null; } }

然后在数据库上下文的 OnModelCreating 中:

modelBuilder.Entity<MyModelName>().HasQueryFilter(c => !c.IsDeleted);

但是在尝试将其转换为 SQL 时会抛出错误。 我阅读了类似问题的解决方案。但 我不打算通过 SQL 语句直接在数据库中创建新的计算列;正如我所说,我不希望它映射到任何现有列。 只是想知道这样的事情是否可能。

asp.net .NET sql-server entity-framework-core

评论

2赞 Svyatoslav Danyliv 11/2/2023
为什么不直接定义可翻译的过滤器呢?无论如何,可以使用第三方扩展或自定义拦截器。HasQueryFilter(c => c.DeleteTime == null)

答:

1赞 Steve Py 11/2/2023 #1

查询筛选器和将表达式转换为 SQL 的任何其他 Linq 操作不能包含自定义函数或属性,因为 SQL 无法执行该代码。因此,你要么需要以一种可以直接翻译的方式编写你的过滤器,比如 Svyatoslav 的评论,要么如果你想将它们关联到一个实体或类似基 Entity 类的东西:

public abstract class SoftDeleteEntity
{
     public int Id { get; protected set; }
     public DateTime? DeleteTime { get; set; } = null;

     public static Expresssion<Func<TEntity, bool>> IsDeletedExpr => (e) => e.DeletedTime != null;
}

假设您的实体有一个支持软删除的基类,否则可以将其直接放入实体中。

然后,当您要应用查询筛选器或 Where 子句时:

modelBuilder.Entity<MyModelName>()
    .HasQueryFilter(SoftDeleteEntity.IsDeletedExpr);

如果你想让过滤器更加封装,这应该可以解决问题。

评论

0赞 Amin 11/4/2023
实际上,将其定义为表达式更接近我的意思,而不是具有自定义拦截器;因为它会涉及许多变化,这是不值得的。泰。