过滤所有查询(尝试实现软删除)

时间:2017-07-14 07:07:52

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

我正在尝试在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);
}

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

1 个答案:

答案 0 :(得分:14)

无法测试确切的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);
}