This is a migrated thread and some comments may be shown as answers.

Problem in Linq query compiler

4 Answers 155 Views
LINQ (LINQ specific questions)
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Noam Berda
Top achievements
Rank 1
Noam Berda asked on 11 Oct 2011, 01:59 AM
Hi,
I have a short code that add dynamically order by query to an existing query.
This code works fine on EF4.1 but doesn't work on Telerik ORM.

Here is the exception
System.NullReferenceException: Object reference not set to an instance of an object. at Telerik.OpenAccess.Query.ExpressionCompiler.PerformDatabaseQueryImpl(Type type, Int32 elementAt, Object[] groupResolutionParamValues, Boolean single, Boolean checkOid) at Telerik.OpenAccess.Query.ExpressionCompiler.PerformDatabaseQuery(Type type, Int32 elementAt, Object[] groupResolutionParamValues, Boolean single, Boolean checkOid)

here is the linq query that been built
{Extent<XXXX.DB.Report>().Where(x => (x.inStatus == Convert(value(XXXXX.Services.Services.ReportService+<>c__DisplayClass2).statusFilter))).OrderBy(Param_0 => Param_0.Address)}

And here is the code that creates it. i think its a problem with Param_0 variable name, but this the default name when i am using the Parameter expression.
public IQueryable<T> ApplyOrder(IQueryable<T> source)
        {
 
            var sortOrder = (_sortOrder == SortOrder.Ascending) ?
                                "OrderBy" : "OrderByDescending";
            
 
            ParameterExpression[] parameters = new ParameterExpression[] {
                Expression.Parameter(typeof(T)) };
 
            //Dig into lambda expression
            Type fieldType = null;
            MemberExpression memberExpression = null;
            Type t = typeof(T);
            string[] tokenFieldName = _orderByField.Split('.');
            
            foreach (var s in tokenFieldName)
            {
                var properties = TypeDescriptor.GetProperties(t);
                var property = properties[s];
                if (property != null)
                {
                    t = fieldType = property.PropertyType;
                    if (memberExpression == null)
                    {
                        memberExpression = Expression.Property(parameters[0], s);
                    }
                    else
                    {
                        memberExpression = Expression.Property(memberExpression, s);
                    }
                }
                else
                {
                    throw new Exception(string.Format("Cannot find field with name '{0}'", _orderByField));
                }
            }
 
            if (memberExpression != null)
            {
                Expression queryExpr = Expression.Call(
                    typeof(Queryable), sortOrder,
                    new Type[] { typeof(T), fieldType },
                    source.Expression, Expression.Quote(Expression.Lambda(memberExpression, parameters)));
                source = source.Provider.CreateQuery<T>(queryExpr);
 
                return source;
            }
            else
            {
                throw new NullReferenceException("No memberExpression was constructed");
            }
            
        }


4 Answers, 1 is accepted

Sort by
0
Thomas
Telerik team
answered on 11 Oct 2011, 04:07 PM
Hi Noam Berda,

I can't find an issue there. I've used your code, and the ordering is doing what it should do.
So, there it could be bound to the inStatus field and the parameter; of which type are they?

Best wishes,
Thomas
the Telerik team

Check out the latest stable build of Telerik OpenAccess ORM. Download it and benefit from our new Project Templates.

0
Noam Berda
Top achievements
Rank 1
answered on 11 Oct 2011, 05:52 PM
Hi Thomas,
I have tried to reproduce it for you so you can see the problem. It looks related to the way the param name are been translated. when i am writing the same query in linq then i can see the param name some how get translated to var1. but when i am using the sample code i gave you the param name is kept at "Param_0" i have seen it when i am looking on the Expression.DebugView of the query and comparing the linq vs ApplyOrder method.

Here is how to reproduce it. take your context, and get all the objects of specific entity. (I am using my Report object but i think it will work on any one). Then apply the order filter to the query with the field name and call ToList. it should then throw the exception.

Hope you can reproduce it.
Noam

var q = _xxxxeContext.Reports;
q = ApplyOrder(q, "Address");
var g = q.ToList();

use the following method to apply the order by.

       public IQueryable<T> ApplyOrder<T>(IQueryable<T> source, string fieldName)
        {
 
            var sortOrder = "OrderBy";
 
 
            ParameterExpression[] parameters = new ParameterExpression[] {
                Expression.Parameter(typeof(T)) };
 
            //Dig into lambda expression
            Type fieldType = null;
            MemberExpression memberExpression = null;
            Type t = typeof(T);
            string[] tokenFieldName = new string[] { fieldName };
 
            foreach (var s in tokenFieldName)
            {
                var properties = TypeDescriptor.GetProperties(t);
                var property = properties[s];
                if (property != null)
                {
                    t = fieldType = property.PropertyType;
                    if (memberExpression == null)
                    {
                        memberExpression = Expression.Property(parameters[0], s);
                    }
                    else
                    {
                        memberExpression = Expression.Property(memberExpression, s);
                    }
                }
            }
 
            if (memberExpression != null)
            {
                Expression queryExpr = Expression.Call(
                    typeof(Queryable), sortOrder,
                    new Type[] { typeof(T), fieldType },
                    source.Expression, Expression.Quote(Expression.Lambda(memberExpression, parameters)));
                source = source.Provider.CreateQuery<T>(queryExpr);
 
                return source;
            }
            else
            {
                throw new NullReferenceException("No memberExpression was constructed");
            }
 
        }
0
Thomas
Telerik team
answered on 12 Oct 2011, 11:08 AM
Hello Noam Berda,

I've rechecked and even used your code in our test suite, but I'm afraid I do not see the effect. Are you really using the latest version ? Older versions did rely on the name of the parameters, newer versions rely on the reference of the parameter expression. You can also give the parameter an explicit name to see if Param_0 is really an issue (again, not on my side).

All the best,
Thomas
the Telerik team

Check out the latest stable build of Telerik OpenAccess ORM. Download it and benefit from our new Project Templates.

0
Noam Berda
Top achievements
Rank 1
answered on 13 Oct 2011, 08:13 AM
Hi Thomas,
I have checked and i am using the latest ORM release.
I have found a workaround for now and will continue to monitor this and will let you know if its coming back.

the workaround was to change the order when i build the linq statement. apparently it solved the problem.

Noam
Tags
LINQ (LINQ specific questions)
Asked by
Noam Berda
Top achievements
Rank 1
Answers by
Thomas
Telerik team
Noam Berda
Top achievements
Rank 1
Share this question
or