【问题标题】:I need to call an EntityFunctions method in a dynamic EF Filter generation. How?我需要在动态 EF 过滤器生成中调用 EntityFunctions 方法。如何?
【发布时间】:2015-07-15 19:25:28
【问题描述】:

我们已经实现了一种使用反射和其他方法动态创建 Lambda 过滤器的方法。我想要的大部分工作都很漂亮。问题在于 DateTime 值和相等/大于/小于过滤器。

我们的 SQL 服务器将项目存储为 DateTime 对象,有时会为特定项目指定时间。但是,当在网络上显示列表时,我们只显示日期。因此,当用户(使用 Kendo Grid)尝试将数据过滤为大于或类似的日期时,它使用当天的午夜作为参数。这意味着当天午夜之后发生的所有项目在不应该出现的情况下都包括在内。这也意味着当我们使用 equals 语句时,不会返回任何内容,因为在午夜发生的事情很少。

我的研究(使用 Stack Overflow)导致我使用 EntityFunctions.TruncateTime 作为一种方法。我不确定是否要对字段和过滤值都执行此操作,但我现在什至无法超过该值。

我的第一次尝试是将比较的右侧(值部分)设置为对EntityFunctions.TruncateTime(filter.Value) 的调用。这给了我一个This function can only be invoked by linq to entities 错误。进一步的研究使我使用了 Expression.Call 方法,但目前我遇到了 No method 'TruncateTime' on type 'System.Data.Objects.EntityFunctions' is compatible with the supplied arguments. 的异常

下面是我尝试拨打电话的代码。我为上下文提供了整个函数。我创建了一个 GetPropertyType 函数来让我知道我是否正在过滤 DateTime 字段。我还在我的 Filter 对象中添加了一个属性来告诉我是否应该忽略时间。如果两者都是真的,那么我才会尝试应用 TruncateTime 函数。

我还尝试将 DateTime 的类型指定为方法中 Expression.Constant 调用的类型参数,以防万一需要键入,但这也无济于事。

    public static Expression GetLambdaFilters(ICollection<Filter> filters)
    {
        if (filters.Count > 0)
        {
            Type entityType = filters.ElementAt(0).EntityType;
            var item = Expression.Parameter(entityType, entityType.Name);
            Expression leftSide = null;
            Expression rightSide = null;
            Expression filterExpression = null;
            foreach (var filter in filters)
            {

                Expression left = GetPropertyExpression(filter, item);
                Expression comparison = null;
                if (left is MethodCallExpression)
                {
                    comparison = left;
                }
                else
                {
                    Expression right = null;
                    if (!filter.IsCollectionQuery)
                    {
                        if (GetPropertyType(filter) == typeof (DateTime) && filter.IgnoreTime)
                        {
                                right = Expression.Call(typeof (EntityFunctions), "TruncateTime", null,
                                    Expression.Constant(filter.Value));
                        }
                        else
                        {
                            right = Expression.Constant(filter.Value);
                        }


                    }
                    else
                    {
                        Filter innerFilter = new Filter();
                        innerFilter.IsCollectionQuery = false;
                        innerFilter.Operator = filter.Operator;
                        innerFilter.PropertyName = GetCollectionPropertyName(filter, item);
                        innerFilter.Type = filter.CollectionType;
                        innerFilter.Value = filter.Value;
                        List<Filter> innerfilters = new List<Filter>(){
                        innerFilter
                    };
                        right = GetLambdaFilters(innerfilters);
                        filter.Operator = FilterOperator.Any;
                    }
                    comparison = GetExpression(left, right, filter);
                }
                if (leftSide == null)
                {
                    leftSide = comparison;
                    filterExpression = leftSide;
                    continue;
                }
                if (rightSide == null)
                {
                    rightSide = comparison;
                    filterExpression = Expression.AndAlso(leftSide, rightSide);
                    continue;
                }
                filterExpression = Expression.AndAlso(filterExpression, comparison);
            }
            var func = typeof(Func<,>);
            func.MakeGenericType(entityType, typeof(bool));
            return Expression.Lambda(func.MakeGenericType(entityType, typeof(bool)), filterExpression, item);
        }
        else
        {
            return GetLambdaFilter(filters.First());
        }
    }

【问题讨论】:

    标签: c# linq entity-framework datetime


    【解决方案1】:

    如果换行:

    right = Expression.Call(typeof (EntityFunctions), "TruncateTime", null,
                                    Expression.Constant(filter.Value));
    

    right = Expression.Call(typeof (EntityFunctions), "TruncateTime", null,
    Expression.Convert(Expression.Constant(DateTime.Parse(filter.Value)), typeof(DateTime?)));
    

    这应该可以。如果没有导致错误的转换调用,它的拳击转换部分就不会发生。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-25
      • 2012-09-03
      • 2014-02-14
      • 1970-01-01
      • 1970-01-01
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多