Testing on null instance causes an exception.

Posts   
 
    
PatrickD
User
Posts: 65
Joined: 05-Sep-2006
# Posted on: 05-Aug-2009 15:57:40   

Hi,

Consider the following Linq query:


UserParameter param1 = null;
var query = from emp in metaData.Employee 
              where param1 == null || emp.ID == param1.ID select emp;

In this query I want to read only the employee with the ID specified by the user. If the user specifies no ID (param1 == null) I want to return all employees.

This works in Linq to Objects, because due to the shortcut OR, param1.ID is not evaluated if param1 == null. In Linq to LLBLGen I get a NullReferenceException, probably because param1.ID is evaluated always, even if param1 == null.

Stack trace:


System.NullReferenceException: Object reference not set to an instance of an object.
at SD.LLBLGen.Pro.LinqSupportClasses.LinqUtils.ObtainRealValueFromConstantWrapped(MemberExpression expressionToHandle, Expression memberContainer)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMemberIsPartOfConstant(MemberExpression expressionToHandle, Expression memberContainer)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMemberExpression(MemberExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleInMemoryEvalCandidateExpression(InMemoryEvalCandidateExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleBinaryExpression(BinaryExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleBinaryExpression(BinaryExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleBinaryExpressionBooleanOperator(BinaryExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleBinaryExpression(BinaryExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleBinaryExpression(BinaryExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleBinaryExpressionBooleanOperator(BinaryExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleLambdaExpression(LambdaExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallWhere(MethodCallExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleQueryableExtensionMethod(MethodCallExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallPerType(MethodCallExpression expressionToHandle, Type declaringType)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallExpression(MethodCallExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleAggregateFunctionMethodCall(MethodCallExpression expressionToHandle, AggregateFunction function)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleQueryableExtensionMethod(MethodCallExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallPerType(MethodCallExpression expressionToHandle, Type declaringType)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallExpression(MethodCallExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleExpression(Expression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.HandleExpressionTree(Expression expression)
at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.Execute(Expression expression)
at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.System.Linq.IQueryProvider.Execute<TResult>(Expression expression)
at System.Linq.Queryable.Count<TSource>(IQueryable`1 source)
at IPParking.ParkBase.TestSuite.EmployeeFixture.Test2()

Kind regards,

Patrick

Walaa avatar
Walaa
Support Team
Posts: 14951
Joined: 21-Aug-2005
# Posted on: 05-Aug-2009 17:34:57   

Please try the following, otherwise is not supported.

UserParameter param1 = null;

var query = null;

if(param1 == null)
{
query = from emp in metaData.Employee 
             select emp;
}
else
{
query = from emp in metaData.Employee 
             where emp.ID == param1.ID 
             select emp;
}
PatrickD
User
Posts: 65
Joined: 05-Sep-2006
# Posted on: 05-Aug-2009 17:40:07   

Walaa wrote:

Please try the following, otherwise is not supported.

UserParameter param1 = null;

var query = null;

if(param1 == null)
{
query = from emp in metaData.Employee 
             select emp;
}
else
{
query = from emp in metaData.Employee 
             where emp.ID == param1.ID 
             select emp;
}

Well, yeah, that is quite obvious smile , but unfortunately normally my queries are not that simple and it is error prone when I have to make a change to the query and thus to all variants of it. Not to mention when more than 1 parameters are nullable. Too bad it is not supported.

Thanks anyway,

Patrick

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39618
Joined: 17-Aug-2003
# Posted on: 06-Aug-2009 09:42:59   

You have to take this route as the constant predicate (param==null, which resolves to 'true', a constant predicate) is not supported in our query system and the provider doesn't optimize these away.

I don't agree it's more error prone, you effectively test for nullability, which is IMHO a good thing. You can use the predicate builder class (see http://www.llblgen.com/TinyForum/Messages.aspx?ThreadID=14224) for dynamically append where clauses easily, so it shouldn't be that hard to write the queries in a more complex scenario.

Frans Bouma | Lead developer LLBLGen Pro