vendredi 16 octobre 2020

C# Dynamic Expression Equal for Nullable Datetime

I am trying to figure it out how to create a predicate using ExpressionType.Equal to compare a Nullable Datetime with a static date or with a user input.

Below I am gonna give a simple example

public class Example 
{
    public int Id { get; set; }

    public string Name { get; set; }

    public DateTime? Test { get; set; }
}

public class PredicateBuilder 
{
        public static Expression<Func<T, bool>> Create<T>(string memberPath,
            string operatorName,
            object targetValue)
        {
            var param = Expression.Parameter(typeof(T), "item");
            var left = memberPath
                .Split(CommonConstants.Separator)
                .Aggregate((Expression)param, Expression.PropertyOrField);
            var underlyingType = Nullable.GetUnderlyingType(left.Type);
            var memberType = underlyingType ?? left.Type;

            Expression exp;

            if (Enum.TryParse(operatorName, out ExpressionType tBinary))
            {
                var right = Expression.Constant(Convert.ChangeType(targetValue, memberType));
                var typeFilter = Expression.Convert(right, left.Type);

                exp = Expression.MakeBinary(tBinary, left, typeFilter);                   
            }
            else
            {
                exp = Expression.Call(
                    left,
                    operatorName, // method
                    Type.EmptyTypes, // no generic type arguments
                    Expression.Constant(Convert.ChangeType(targetValue, memberType)) // argument
                );
            }

            return Expression.Lambda<Func<T, bool>>(exp, param);
        }
}


// In my concrete implementantion came up the need of comparing a certain date with 1900/1/1

IQueryable<Example> allExamples = ...;
var filterExpression = filterExp = PredicateBuilder.Create<Example>("Test", 
                                    nameof(ExpressionType.Equal),
                                    new DateTime(1900, 1, 1));

allExamples = allExamples.Where(filterExpression);

Problem

I've tried a few solutions but I am always getting an exception related with a string conversion don't know why.

Generated Expression

{item => (item.Test == Convert(1/1/1900 12:00:00 AM, Nullable`1))}

"Conversion failed when converting date and/or time from character string."

Any thoughts on this?

Update

I am using EF Core and datetime for the SQL date columns

I just noticed that if I do the filter manually will produce the same error

allExamples = allExamples.Where(x => x.Test == new Datetime(1900, 1, 1));

but if you declare the variable it works fine

var date = new Datetime(1900, 1, 1);
allExamples = allExamples.Where(x => x.Test == date);

How to create an expression dynamically to work like this last example?

Thanks





Aucun commentaire:

Enregistrer un commentaire