David Ortega
David Ortega

Reputation: 915

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. 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. But the compiler throws an error stating T is already defined. 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();
    }
}

Upvotes: 0

Views: 942

Answers (2)

mostafa
mostafa

Reputation: 289

using this method you can pass custom where clause to to your GetAll Method

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.

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

Upvotes: 0

bassfader
bassfader

Reputation: 1356

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".

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:

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 (i.e. change it to where TCrud : class, CRUDProperties)

Upvotes: 1

Related Questions