Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cast Entity to Implemented Interface in a Generic Method Using LINQ for Entity Framework

I have a generic method to query objects of type TEntity in EF. I Want to add a condition as a where clause if TEntity implements a specific interface. The method I have is:

public TEntity GetByUserID(Guid userID)
{
    var query = this.DbSet;
    if (typeof (TEntity).IsImplementationOf<IDeletableEntity>())
    {
        query = query
            .Where((x => !((IDeletableEntity)x).IsDeleted);
    }
    return query
        .FirstOrDefault(x => x.UserID == userID);
}

IsImplementationOf<>() is method which just returns true/false as the name implies.

When I run this for the entity Address which implement IDeletableEntity, I get an error:

Unable to cast the type 'Address' to type 'IDeletableEntity'. LINQ to Entities only supports casting EDM primitive or enumeration types.

Any ideas how I can go around this limitation of LINQ?

like image 911
Vladimir Avatar asked Mar 23 '15 20:03

Vladimir


1 Answers

This is a working solution:

public TEntity GetByUserID(Guid userID, params Include<TEntity>[] includes)
{
    var query = this.DbSet;
    query = Where<IDeletableEntity>(query, x => !x.IsDeleted);
    return query
        .FirstOrDefault(x => x.UserID == userID);
}

public static IQueryable<TEntity> Where<TPredicateWellKnownType>(IQueryable<TEntity> query, Expression<Func<TPredicateWellKnownType, bool>> predicate)
{
    if (typeof(TEntity).IsImplementationOf<TPredicateWellKnownType>())
    {
        query = ((IQueryable<TPredicateWellKnownType>)query)
            .Where(predicate)
            .Cast<TEntity>();
    }
    return query;
}
like image 143
Vladimir Avatar answered Oct 22 '22 00:10

Vladimir