Search code examples
c#linqentity-framework-coredbfunctions

.NET Core Expression DbFunctions DiffDays


I have an extension I have written for the date filter using the DiffDays method with .NET. In .NET Core, EF.Functions was replaced by DbFunctions, so it could not execute it.

My .NET Code

 private static (ParameterExpression param, MemberExpression prop) QueryExpressions<Entity>(IQueryable<Entity> query, string property)
        {
            var param = Expression.Parameter(query.ElementType, "x");
            MemberExpression prop;

            if (property.Contains('.'))
            {
                string[] childProperties = property.Split('.');

                prop = Expression.Property(param, childProperties[0]);

                for (int i = 1; i < childProperties.Length; i++)
                    prop = Expression.Property(prop, childProperties[i]);
            }
            else
                prop = Expression.Property(param, property);

            return (param, prop);
        }

 public static IQueryable<Entity> DiffDaysLessThan<Entity>(this IQueryable<Entity> query, string property, object value)
        {
            var methodInfo = typeof(DbFunctions).GetMethod("DiffDays", new Type[] { typeof(DateTime?), typeof(DateTime?) });

            (ParameterExpression param, MemberExpression prop) = QueryExpressions(query, property);

            var left = Expression.Call(
                methodInfo,
                Expression.Convert(Expression.Constant(value), typeof(DateTime?)), Expression.Convert(prop, typeof(DateTime?)));
            var right = Expression.Convert(Expression.Constant(0), typeof(int?));

            var body = Expression.LessThanOrEqual(left, right);

            return query.Where(Expression.Lambda<Func<Entity, bool>>(body, param));
        }

.NET CORE

   public static IQueryable<Entity> DiffDaysLessThan<Entity>(this IQueryable<Entity> query, string property, object value)
        {

            var methodInfo = typeof(SqlServerDbFunctionsExtensions).GetMethod("DateDiffSecond", new Type[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) });

            (ParameterExpression param, MemberExpression prop) = QueryExpressions(query, property);

            var left = Expression.Call(
                methodInfo,
                Expression.Convert(Expression.Constant(value), typeof(DateTime?)), Expression.Convert(prop, typeof(DateTime?)));
            var right = Expression.Convert(Expression.Constant(0), typeof(int?));

            var body = Expression.LessThanOrEqual(left, right);

            return query.Where(Expression.Lambda<Func<Entity, bool>>(body, param));
        }

I could not equals the typeof (DbFunctions) parameter on the Expression.Call side when calling the method.

ERROR

System.ArgumentException: Incorrect number of arguments supplied for call to method 'System.Nullable1[System.Int32] DateDiffSecond(Microsoft.EntityFrameworkCore.DbFunctions, System.Nullable1[System.DateTime], System.Nullable`1[System.DateTime])' (Parameter 'method')


Solution

  • EF Core functions are extension methods of DbFunctions class returned by EF.Functions property. So although unused, you have to pass the first argument of type DbFunctions when calling them, e.g.

    var left = Expression.Call(
        methodInfo,
        Expression.Constant(EF.Functions, typeof(DbFunctions)), // <--
        Expression.Convert(Expression.Constant(value), typeof(DateTime?)),
        Expression.Convert(prop, typeof(DateTime?)));