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:
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;
}
I think the problem might be the direct cast you are doing in your statement as well as query might be implementing enumeration types and so IDeletable is not implemented as on one entity.
LINQ-to-entities casting issue
proposed this solution.
return query.ToList()
.Cast<IDeletable>()
.Where( e => e.Deleted )
.Cast<T>();
If all DbSets has the 'UserID' property then create another interface named 'IUserID' and then try this code:
protected TEntity GetByUserID<TEntity>(Guid userID) where TEntity : class
{
var user = this.Set<TEntity>()
.ToList()
.Cast<IDeletableEntity>()
.Where(u => (!u.IsDeleted))
.Cast<IUserID>()
.Where(u => (u.UserID == userID))
.FirstOrDefault();
return user;
}