Динамическая фильтрация c, невозможно получить имя свойства динамически - PullRequest
0 голосов
/ 12 марта 2020

Это мой код:

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 объекта.

Заранее благодарим за помощь.

1 Ответ

0 голосов
/ 12 марта 2020

Я нашел решение этой проблемы.

Я построил дерево выражений до вызова лямбда-выражения в предложении 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);
                        }
                    }
                }

Если это может помочь ...

...