简体   繁体   English

实体框架的通用位置对于从特定类继承的实体

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

Here I have a generic Repository class I copied from a tutorial page, but specifically my problem is on the two last functions. 在这里,我有一个通用的Repository类,该类是从教程页面复制的,但是具体来说,我的问题在于最后两个函数。 On my project I have several catalog entities that inherit from CRUDProperties class and there is a property "Activo" in all of them, what I currently want to do is that if the entity inherits from CRUDProperties class I get all the entities with Activo property on true, and if they do not inherit from that class it just gets all entities. 在我的项目中,我有几个继承自CRUDProperties类的目录实体,并且所有实体中都有一个属性“ Activo”,我现在要做的是,如果该实体继承自CRUDProperties类,则将所有具有Activo属性的实体是的,如果它们不从该类继承,则仅获取所有实体。 But the compiler throws an error stating T is already defined. 但是编译器抛出错误,表明T已经定义。 What should I do? 我该怎么办?

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();
    }
}

The compiler complains about the ambiguous naming of the type parameters. 编译器抱怨类型参数的命名不明确。 The class already has a type parameter named T , so in the context of the class that type parameter name is already "taken". 该类已经有一个名为T的类型参数,因此在类的上下文中,该类型参数名称已被“采用”。

But you should be able to accomplish what you want to do simply by renaming the type parameter for the method to something else than T , so your changed method could look like this: 但是您应该能够简单地通过将方法的类型参数重命名为T其他东西来完成您想做的事情,因此更改后的方法看起来像这样:

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

Note: I assume here that CRUDProperties is a class... If it is an interface then you'll also need to copy the class constraint to the method (ie change it to where TCrud : class, CRUDProperties ) 注意:我在这里假设CRUDProperties是一个类...如果它是一个接口,那么您还需要将class约束复制到方法中(即,将其更改为where TCrud : class, CRUDProperties

using this method you can pass custom where clause to to your GetAll Method 使用此方法,您可以将自定义where子句传递给GetAll方法

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

In this method we first check if the T type have Activo property, If find this property so we create a custom expression tree and replace with default predicate that returns all records, this function only returns records that have true value in activo property. 在此方法中,我们首先检查T类型是否具有Activo属性,如果找到此属性,则我们创建一个自定义表达式树并替换为返回所有记录的默认谓词,此函数仅返回activo属性中值为true的记录。

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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM