1

How do we create an AS expression in Expression tree builder? https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/type-testing-and-cast#as-operator

We have an Iqueryable, we want to check a property of the object. By doing so we use Expression.Convert to convert the parameterexpression to a class. Afterwards we get an error we try to run this query on the DbContext: 'Unable to cast the type 'System.Object' to type 'System.Data.Entity.DynamicProxies.Ourclass'. LINQ to Entities only supports casting EDM primitive or enumeration types.'

Code we use:

        Expression<Func<object, bool>> Example<T>(T customeType)
        {
            ParameterExpression e = Expression.Parameter(typeof(object));
            var converted =  Expression.Convert(e, customeType.GetType());
            MemberExpression u = Expression.MakeMemberAccess(converted, "IsDeleted");           
            BinaryExpression isDeleted = Expression.Equal(u, Expression.Constant(false));
            Expression<Func<object, bool>> lambda = Expression.Lambda<Func<object, bool>>(isDeleted, e);
            return lambda;
        }

The above code compiles to something like: m => ((OurClass)m).IsDeleted == false. However this is not valid code for Linq to Entities. We want something like m => (m as OurClass).IsDeleted == false. Is it possible to generate a dynamic expression? We do not want to use ToList for performance reasons.

Jesper1
  • 78
  • 7

2 Answers2

2

The equivalent of:

(OurClass)x

is:

Expression.Convert(x, typeof(Ourclass));

The equivalent of:

x as OurClass

is:

Expression.TypeAs(x, typeof(OurClass));

Note that you should always check the result of an as cast to see whether the cast failed and the result is null.


An easy way to investigate expressions is to get the compiler to construct them. For your case, I wrote:

Expression<Func<object, string>> foo = x => x as string;

You can then either look at foo in a debugger, or put that into SharpLab and see what the compiler generates.

canton7
  • 37,633
  • 3
  • 64
  • 77
  • Hello @canton7 thanks for the answer. After using TypeAs we get the error: "input of type 'System.Object' and a check of type 'System.Data.Entity.DynamicProxies.OurClass' is not supported. Only entity types and complex types are supported in LINQ to Entities queries.'" when we use ToList(). – Jesper1 Nov 22 '19 at 15:52
  • @Jesper1 Indeed. I answered your question, but I think you asked the wrong question -- the question is how you do casting of any type with EF, not how to do s specific sort of cast. Perhaps look at [this question](https://stackoverflow.com/questions/18976495/linq-to-entities-only-supports-casting-edm-primitive-or-enumeration-types-with-i)? – canton7 Nov 22 '19 at 15:56
0

One solution is to wrap your as expression in a method:

public static TResult As<T, TResult>(T obj)
    where TResult : class
{
    return obj as TResult;
}

Then use a MethodCallExpression to activate it.

Aly Elhaddad
  • 1,913
  • 1
  • 15
  • 31