【问题标题】:Filter all queries (trying to achieve soft delete)过滤所有查询(试图实现软删除)
【发布时间】:2017-07-14 07:07:51
【问题描述】:

我正在尝试在 EF Core 2.0 中使用软删除行为。

public interface ISoftDeleteModel
{
    bool IsDeleted { get; set; }
}

创建正确的列和软删除工作正常,但从 DbContext 过滤实体却不行。

我想在上下文中使用查询过滤,但我卡住了。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    Type entityType;
    // ^^^ it contains type of entity, eg. Blog, Post, etc. using
    // modelBuilder.Model.GetEntityTypes().First().Name and converting to Type

    var entity = modelBuilder.Entity(entityType);
    if(entityType.GetInterface("ISoftDeleteModel") != null)
    {
        // ??? how to access IsDeleted property ???
        entity.HasQueryFilter(x => !x.IsDeleted);
    }
}

问题很简单——如何访问 IsDeleted 属性?

如果我知道实体的类型,例如。 Post 和 Post 实现了 ISoftDeleteModel 我可以这样做:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Post>().HasQueryFilter(x => !x.IsDeleted);
}

但我不知道类型。我正在尝试实现简单的事情-实现此接口的所有模型都将被自动过滤。我错过了什么吗?

【问题讨论】:

    标签: c# entity-framework .net-core entity-framework-core


    【解决方案1】:

    无法测试确切的 API,但一般方法是创建一个受约束的泛型方法并通过反射调用它:

    public static class EFFilterExtensions
    {
        public static void SetSoftDeleteFilter(this ModelBuilder modelBuilder, Type entityType)
        {
            SetSoftDeleteFilterMethod.MakeGenericMethod(entityType)
                .Invoke(null, new object[] { modelBuilder });
        }
    
        static readonly MethodInfo SetSoftDeleteFilterMethod = typeof(EFFilterExtensions)
                   .GetMethods(BindingFlags.Public | BindingFlags.Static)
                   .Single(t => t.IsGenericMethod && t.Name == "SetSoftDeleteFilter");
    
        public static void SetSoftDeleteFilter<TEntity>(this ModelBuilder modelBuilder) 
            where TEntity : class, ISoftDeleteModel
        {
            modelBuilder.Entity<TEntity>().HasQueryFilter(x => !x.IsDeleted);
        }
    }
    

    现在您可以在 OnModelCreating 中使用类似的内容:

    foreach (var type in modelBuilder.Model.GetEntityTypes())
    {
        if (typeof(ISoftDeleteModel).IsAssignableFrom(type.ClrType))
            modelBuilder.SetSoftDeleteFilter(type.ClrType);
    }
    

    【讨论】:

    • 我将不得不仔细阅读并尝试理解您的答案。但它有效。谢谢
    • 嗨,我应该如何编辑该方法以使其在继承方案中工作,并将ISoftDeleteModel 应用于基本抽象类型?谢谢。
    • @m.phobos 您好,您所说的继承方案是指 EF 继承 (TPH) 还是类继承?
    • @m.phobos 没问题,抱歉耽搁了。这是修改后的if 条件:typeof(ISoftDeleteModel).IsAssignableFrom(type.ClrType) &amp;&amp; (type.BaseType == null || !typeof(ISoftDeleteModel).IsAssignableFrom(type.BaseType.ClrType))
    • @IvanStoev 抱歉耽搁了,我一直很忙,之前无法测试您的解决方案。我已根据您的建议更改了 if 条件。我在应用迁移时仍然遇到问题。 Add-Migration 命令失败并出现以下错误:The filter expression 'x =&gt; Not(x.IsDeleted)' cannot be specified for entity type '&lt;Inherited Concrete Type&gt;'. A filter may only be applied to the root entity type in a hierarchy. 请您有任何进一步的建议吗?我还缺少其他东西吗?谢谢!
    猜你喜欢
    • 2016-07-08
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多