首页 > 解决方案 > 动态过滤,无法动态获取属性名实体框架

问题描述

这是我的代码:

Func<TransportFilterModel, IQueryable> filterData = (filterModel) =>
            {
                IQueryable<Transport> query = _context.Set<Transport>();

                foreach(PropertyInfo prop in filterModel.GetType().GetProperties())
                {
                    var type = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;

                    if(prop.GetValue(filter) != null)
                    {
                        if(type == typeof(bool))
                        { 
                            query = query.Where(p => p.GetType().GetProperty(prop.Name).GetValue(p, null).Equals(prop.GetValue(filterModel)));
                        }
                    }
                }

                query = query.Skip((filterModel.Page - 1) * filter.Limit).AsQueryable();


                return filterModel.Limit == 0 ? query : query.Take(filterModel.Limit); //If filterModel.Limit == 0, illimited data on page, no pagination

问题出在 where 子句中。我尝试使用反射来动态获取属性的名称。然后过滤器对象的属性应该与实体传输属性匹配。

这是来自控制台的响应:

System.InvalidOperationException: The LINQ expression 'Where<Transport>(
    source: DbSet<Transport>, 
    predicate: (t) => t.GetType().GetProperty((Unhandled parameter: __prop_Name_0)).GetValue(
        obj: t, 
        index: null).Equals((Unhandled parameter: __GetValue_1)))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

我尝试使用“==”而不是 Equals,但仍然遇到相同的错误。此外,我们正在比较 2 个对象。

预先感谢您的帮助。

标签: entity-frameworklinqfilteringwhere-clause

解决方案


我找到了解决这个问题的方法。

在将 lambda 表达式调用到 Where 子句之前,我构建了一个表达式树。像这样 :

foreach(PropertyInfo prop in filterModel.GetType().GetProperties())
                {
                    var type = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;

                    if(prop.GetValue(filterModel) != null)
                    {
                        if (type == typeof(bool))
                        {
                            ParameterExpression parameter = Expression.Parameter(typeof(Transport), "x");
                            Expression property = Expression.Property(parameter, prop.Name);
                            Expression target = Expression.Constant(prop.GetValue(filterModel));
                            Expression equalsMethod = Expression.Call(property, "Equals", null, target);
                            Expression<Func<Transport, bool>> lambda = Expression.Lambda<Func<Transport, bool>>(equalsMethod, parameter);
                            query = query.Where(lambda);
                        }
                    }
                }

如果它可以帮助...


推荐阅读