【问题标题】:Entity Framework generic Where for entities that inherit from a specific class实体框架通用 Where 用于从特定类继承的实体
【发布时间】:2017-11-17 00:55:52
【问题描述】:

在这里,我有一个从教程页面复制的通用 Repository 类,但具体而言,我的问题在于最后两个函数。在我的项目中,我有几个从 CRUDProperties 类继承的目录实体,并且在所有这些实体中都有一个属性“Activo”,我目前想要做的是,如果实体从 CRUDProperties 类继承,我将获得所有具有 Activo 属性的实体是的,如果它们不从该类继承,它只会获取所有实体。但是编译器会抛出一个错误,说明 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();
    }
}

【问题讨论】:

  • 你在周围的类Repository&lt;T&gt;中已经有了一个类型参数T。如果您想为该类中的方法添加新的/不同类型的参数,那么您需要为该类型参数指定一个不同的名称。
  • @bassfader 如果我希望它尽可能通用,可以分配任何其他字母?

标签: c# entity-framework repository-pattern


【解决方案1】:

编译器抱怨类型参数的命名不明确。该类已经有一个名为T 的类型参数,因此在该类的上下文中,该类型参数名称已经被“采用”了。

但是您应该能够通过将方法的类型参数重命名为 T 以外的其他名称来完成您想做的事情,因此您更改后的方法可能如下所示:

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

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

【讨论】:

    【解决方案2】:

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

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

    在这个方法中我们首先检查T类型是否有Activo属性,如果找到这个属性我们创建一个自定义表达式树并替换为返回所有记录的默认谓词,这个函数只返回在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);
    }
    

    【讨论】:

    • 这看起来真的很有用,但是当实体从特定类继承时,有没有办法自动应用谓词?这主要是我的意图。
    • 使用反射,检查你的泛型是否有“Activo”属性为这个属性生成一个谓词并用作where cluase
    • 你能用一个例子来扩展你的答案吗?我已经找到了如何获取实体是否继承自一个类,但我无法访问实体属性
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-10
    • 2016-02-05
    • 2011-05-19
    • 2010-10-07
    • 1970-01-01
    相关资源
    最近更新 更多