How to get Expression for Nullable values ( fields ) without converting from Expression.Convert in C#?

c# expression-trees lambda linq-expressions

Question

During the creation of dynamic query expressions, I am working with the scenario of Nullable types. From any SQL Tables, these phrases would get filtered data ( interfacing with Code First classes using EF ).

I have a common item ( e.g Consignment operating on several properties along with Nullable properties).

Everything is going great with my expression creation until I get across certain Nullable types. I'm receiving these nullables on these

The binary operator NotEqual is not defined for the types 'System.Nullable`1[System.Single]' and 'System.Single'.

I am utilizing all conversion-related approaches that have been presented on various boards in order to remove this exception.

Expression trees' use of lambda expressions

attempting to filter using Expression Trees on a Nullable type

All of them are producing expressions with the term "Convert" appended, such as Convert(someValue), and as a consequence, I always have an expression.

t=>(t.Consignment.Id = 45000 && t.Consignment.someProperty>=45 Or t.Consignment.Weight! = Convert(5000)).

Naturally, I need the whole above statement without the word "Convert." Because this "Convert" will not appropriately get the data from tables.

I would be very grateful for any assistance! What has to be done now? Although I am aware of conversion, the unnecessary "Convert" renders the whole statement meaningless since it will not project the data.

Added

   Expression NotEqual<T>(Expression PropertyType, ConstantExpression a_Constant, ParameterExpression parameter)
   {
    if(IsNullableType(Property.Type) &&!IsNullableType(a_Constant.Type))
    {
      var converted = a_Constant.Type != Property.Type ?  (Expression)Expression.Convert(a_Constant, Property.Type): (Expression)a_Constant;

     // here above statement returns (Convert(50000)) and all I want (50000), but i tried all combinitions from Expression in order to form this constant as expression, it always throws exception what I mentioned originally.

     var body = Expression.MakeBinary(ExpressionType.NotEqual, PropertyType,  converted);

    //MakeBinary statement returns {(t.Weight != Convert(5000000))} but I    need {(t.Weight != 5000000)}

     var expr = Expression.Lambda<Func<T, bool>>(body, parameter);
     return expr;
    }
  }

Code:

public class Consignment
{
    public float? Weight { get; set; }
}    

public static class GenericQueryExpressionBuilder
{        
    private static Expression NotEqual<T>(Expression memberExpression, ConstantExpression a_Constant, ParameterExpression parameter)
    {
        ConstantExpression constantExpression = null;

        if (IsNullableType(memberExpression.Type) && !IsNullableType(a_Constant.Type))
        {                
             //var converted = a_Constant.Type != memberExpression.Type ? (Expression)Expression.Convert(a_Constant, memberExpression.Type) : (Expression)a_Constant;

           Expression constantExp =  Expression.Property(a_Constant,typeof(T),"Weight");

        **// above statement throws exception I commented.**

            var body = Expression.MakeBinary(ExpressionType.NotEqual, memberExpression, converted);

            //here I want "t=>(t.Weight!=5000.0) INSTEAD of t=>(t.Weight!=Convert(5000.0))"

            var expr = Expression.Lambda<Func<T, bool>>(body, parameter);
            return expr;
        }

        else if (!IsNullableType(memberExpression.Type) && IsNullableType(a_Constant.Type))
            memberExpression = Expression.Convert(memberExpression, a_Constant.Type);

        return Expression.NotEqual(memberExpression, constantExpression);
    }

    static bool IsNullableType(Type t)
    {
        return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>);
    }        

    private static Expression GetExpression<T>(ParameterExpression param, string a_strPropertyName, string Operator, object Value)
    {            
        MemberExpression member = Expression.Property(param, a_strPropertyName);
        ConstantExpression constant = Expression.Constant(Value);

        try
        {               
           return GenericQueryExpressionBuilder.NotEqual<T>(member, constant, param);             

        }
        catch (InvalidOperationException)
        {
            return null;
        }

        return null;
    }

    public static Expression<Func<T, bool>> GetExpression<T>(Consignment consignment)
    {
        Expression expression = null;

        var parameter = Expression.Parameter(typeof(T), "t");

        string PropertyName = "Weight";
        string Operation = "NotEqual";
        object Value = consignment.Weight;

        expression = GenericQueryExpressionBuilder.GetExpression<T>(parameter, PropertyName, Operation, Value);
        return Expression.Lambda<Func<T, bool>>(expression, parameter);
    }
}
class Program
{
    static void Main(string[] args)
    {


        Consignment consignment = new Consignment();
        consignment.Weight = 50000.0f;

        var deleg = GenericQueryExpressionBuilder.GetExpression<Consignment>(consignment).Compile();            

    }
   }
1
1
5/23/2017 12:24:55 PM

Accepted Answer

Here is a concise yet thorough illustration of how to construct thec => c.Weight.HasValue && c.Weight.Value != 5000f tree of expressions I've cut off a bunch of pointless code from the query:

using System;
using System.Linq.Expressions;

public class Consignment
{
    public float? Weight { get; set; }
}    

public class Test
{        
    private static Expression NotEqual(Expression memberExpression,
                                       ConstantExpression constantToCompare)
    {
        // Other cases removed, for simplicity. This answer only demonstrates
        // how to handle c => c.Weight != 5000f.
        var hasValueExpression = Expression.Property(memberExpression, "HasValue");
        var valueExpression = Expression.Property(memberExpression, "Value");
        var notEqual = Expression.NotEqual(valueExpression, constantToCompare);
        return Expression.AndAlso(hasValueExpression, notEqual);
    }

    static void Main(string[] args)
    {
        Consignment consignment = new Consignment();
        consignment.Weight = 50000.0f;

        var parameter = Expression.Parameter(typeof(Consignment), "c");
        var weight = Expression.Property(parameter, "Weight");
        var constant = Expression.Constant(5000f, typeof(float));
        var weightNotEqualExpression = NotEqual(weight, constant);
        var lambda = Expression.Lambda<Func<Consignment, bool>>
            (weightNotEqualExpression, parameter);
        Console.WriteLine(lambda);
    }
}
8
2/12/2015 11:57:16 AM


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow