The EF expression parser will work without casting, however, you cannot compile C # code without casting (C # will complain that it does not know that TEntity has the Active property). The solution is: cast for the C # compiler, not for the expression for the EF expression parser.
So, if you are sure (you check it if , so that you are) that the object implements IActivable , you can create a cast expression (for compilation) and then remove the casts at runtime (which are not needed) for EF. For your specific case:
public IQueryable<TEntity> GetActive() { if (typeof(IActivable).IsAssignableFrom(typeof(TEntity))) { Expression<Func<TEntity, bool>> getActive = x => ((IActivable)x).Active; getActive = (Expression<Func<TEntity, bool>>)RemoveCastsVisitor.Visit(getActive); return this.repository.Get().Where(getActive); } else { return this.Get(); } }
The expression user looks like this:
internal class RemoveCastsVisitor : ExpressionVisitor { private static readonly ExpressionVisitor Default = new RemoveCastsVisitor(); private RemoveCastsVisitor() { } public new static Expression Visit(Expression node) { return Default.Visit(node); } protected override Expression VisitUnary(UnaryExpression node) { if (node.NodeType == ExpressionType.Convert && node.Type.IsAssignableFrom(node.Operand.Type)) { return base.Visit(node.Operand); } return base.VisitUnary(node); } }
It simply checks if any casting is required: if the actual value already implements the type it refers to, it will simply remove the conversion from the expression and EF will select it correctly.
source share