'CamlexNET.NonSupportedExpressionException' when converting normal LINQ query to Camlex query

Aug 3, 2016 at 7:04 AM
I need to translate normal queries from LINQ to Camlex queries but some problems occured.
for example I have the following expression c => c.ShowInInvoicesGrid == true and I try to translate it to x => (bool)x["CategoriesShowInInvoices"] == true. For this goal I am using a class inheriter of the ExpressionVisitor with the following implementation:
 class Visitor<ListItem, T, TProxy> : ExpressionVisitor
    {
        ParameterExpression parameter;
        Type initialMemberType;
        private IListItemDataUtility<T, TProxy> listItemDataUtility;

        public Visitor(ParameterExpression listItemParam, IListItemDataUtility<T, TProxy> listItemDataUtility)
        {
            this.parameter = listItemParam;
            this.listItemDataUtility = listItemDataUtility;
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            return this.parameter;
        }

        protected override Expression VisitMember(MemberExpression node)
        {
            if (node.Member.MemberType == System.Reflection.MemberTypes.Property)
            {
                MemberExpression memberExpression = null;
                var memberName = node.Member.Name;
                var memberType = node.Member.MemberType;
                var internalName = this.listItemDataUtility.GetFieldInternalNameFromProperty(memberName);
                var newProperty = (Expression.Convert(Expression.Property(this.parameter, "Item", new Expression[] { Expression.Constant(internalName) }), typeof(Boolean)));
                return newProperty;
            }
            else
            {
                return base.VisitMember(node);
            }
        }
    }
Visitor class is used in the following method to generate translated expressions:
 private Expression<Func<ListItem, bool>> ConvertExpression(Expression<Func<T, bool>> expr)
        {
            var listItemParam = Expression.Parameter(typeof(ListItem));
            var visitor = new Visitor<ListItem, T, TProxy>(listItemParam, this.listItemDataUtility);
            var resultingExpression = visitor.Visit(expr.Body);
            Expression<Func<ListItem, bool>> resultingLambda = Expression.Lambda<Func<ListItem, bool>>(resultingExpression, listItemParam);
            return resultingLambda;
        }
the expressions are then moved in a list and passed to the camlex WhereAll() clause:
 caml = caml.WhereAll(andListItemExpressions);
At this last line I receive the NonSupportedExpressionException: An exception of type 'CamlexNET.NonSupportedExpressionException' occurred in Camlex.Client.dll but was not handled in user code

Additional information: Expression 'x => ((Convert(Param_0.Item["CategoriesShowInInvoices"]) == True) AndAlso (Convert(Param_1.Item["CategoriesShowInTemplates"]) == True))' can not be translated into CAML
Coordinator
Aug 17, 2016 at 12:35 PM
hi ttittoCode,
sorry for long reply. As far as I see from your example expression which you passed looks like this:

x => (bool)x["CategoriesShowInInvoices"] == true && (bool)x["CategoriesShowInTemplates"] == true

However if we will check example of WhereAll method (e.g. here) we will see that instead of single expression it should receive 2 separate expressions:

x => (bool)x["CategoriesShowInInvoices"] == true
x => (bool)x["CategoriesShowInTemplates"] == true

(parameter of both expressions should be "x" variable)

Also I didn't dig very detailed into your code, but error message shows that expression which you pass has 2 different parameters Param_0 and Param_1:

x => ((Convert(Param_0.Item["CategoriesShowInInvoices"]) == True) AndAlso (Convert(Param_1.Item["CategoriesShowInTemplates"]) == True))

while logically it should be the same single parameter. Hope that it will guide you in right direction.