Entity Framework 继承自特定 class 的实体的通用 Where

Entity Framework generic Where for entities that inherit from a specific class

这里我有一个通用的存储库 class 我从教程页面复制而来,但具体来说我的问题在于最后两个函数。在我的项目中,我有几个继承自 CRUDProperties class 的目录实体,并且所有这些实体中都有一个 属性 "Activo",我目前想要做的是,如果该实体继承自 CRUDProperties class 我通过 Activo 属性 获得所有实体,如果它们不继承 class 它只会获得所有实体。但是编译器会抛出一个错误,指出 T 已被定义。我该怎么办?

public class Repository<T> where T : class
{
    private readonly projectEntities context;
    private IDbSet<T> entities;
    string errorMessage = string.Empty;

    public Repository(projectEntities context)
    {
        this.context = context;
    }

    public T GetById(object id)
    {
        return context.Set<T>().Find(id);
    }

    // This is the function that throws me a compilation error
    public virtual IList<T> GetAll<T>() where T : CRUDProperties
    {
        return context.Set<T>().Where(c => c.Activo).ToList();
    }

    public virtual IList<T> GetAll()
    {
        return context.Set<T>().ToList();
    }
}

使用此方法,您可以将自定义 where 子句传递给您的 GetAll 方法

public virtual IList<T> GetAll<T>(Expression<Func<T, bool>> predicate)
{
    return context.Set<T>().Where(predicate).ToList();
}

在这个方法中我们首先检查 T 类型是否有 Activo 属性,如果找到这个 属性 那么我们创建一个自定义表达式树并用默认谓词替换 returns 所有记录,此功能仅 returns 在 activo 属性.

中具有真实价值的记录
public virtual IList<T> GetAll<T>()
{
    Expression<Func<T, bool>> predicate = t => true;
    if(typeof(T).GetProperty("Activo") != null)
    {

        var epx = Expression.Parameter(typeof(T), "x");
        Expression left =  Expression.PropertyOrField(epx, "Activo");
        Expression right = Expression.Constant(true);
        Expression e1 = Expression.Equal(left, right);

        predicate = Expression.Lambda<Func<T, bool>>(e1, new ParameterExpression[] { epx });
    }
    return context.Set<T>().Where(predicate);
}

编译器抱怨类型参数的命名不明确。 class 已经有一个名为 T 的类型参数,因此在 class 的上下文中,该类型参数名称已经是 "taken".

但是您只需将方法的类型参数重命名为 T 以外的名称就可以完成您想要的操作,因此您更改后的方法可能如下所示:

public virtual IList<TCrud> GetAll<TCrud>() where TCrud : CRUDProperties
{
    return context.Set<TCrud>().Where(c => c.Activo).ToList();
}

注意:我在这里假设 CRUDProperties 是一个 class... 如果它是一个接口,那么您还需要将 class 约束复制到方法(即将其更改为 where TCrud : class, CRUDProperties)