我有一个动态过滤List的通用方法,最近我将项目更新为NetCore 3.0,此方法不起作用

这是调用方法时遇到的错误。

System.InvalidOperationException: 'The LINQ expression 'Where<Provincia>(
    source: OrderBy<Provincia, string>(
        source: DbSet<Provincia>,
        keySelector: (p) => p.Identificador),
    predicate: (p) => p.GetType().GetProperty((Unhandled parameter: __prop_0)).GetValue(
        obj: (object)p,
        index: null).ToString() == (Unhandled parameter: __value_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.'



这是我的方法

public static IQueryable<T> FilerByProperties(string properiesFilter, IQueryable<T> query)
{
    if (properiesFilter == null) properiesFilter = "";
    string[] properties = properiesFilter.Split(";");

    for (int i = 0; i < properties.Length; i++)
    {
        if(!properiesFilter.IsNullOrEmpty())
        {
            int pocisionProp = properties[i].ToString().IndexOf('=');
            string prop = properties[i].Substring(0, pocisionProp);
            string value = properties[i].Substring(pocisionProp + 1);

            if (typeof(T).GetProperty(prop) != null)
            {
                query = query.Where(x => x.GetType().GetProperty(prop).GetValue(x, null).ToString() == value);
            }
        }
    }
    return query;
}


我这样用

public override Task<PagedResultDto<ProvinciaDto>> GetAllAsync(PagedAndSortedRequest input)
{
    var lista = new List<Provincia>();
    var query = Repository.GetAllIncluding(x => x.Pais);

    query = CreateFilteredQuery(input);
    query = ApplySorting(query, input);
    query = FilterHelper<Provincia>.FilerByProperties(input.FilterProperties, query);


    lista = query
        .Skip(input.SkipCount)
        .Take(input.MaxResultCount)
        .ToList();

    var result = new PagedResultDto<ProvinciaDto>(query.Count(), ObjectMapper.Map<List<ProvinciaDto>>(lista));
    return Task.FromResult(result);
}


input.FilterProperties中,我收到“ PaisId = 1”,在这种情况下,我需要过滤Provincias
具有“ PaisId = 1”

我希望你能帮助我。

最佳答案

Lambda表达式应该在这里为您解决问题。

助手类

public static class ExpressionBuilder
{
    public static Expression<Func<T, bool>> GetExpression<T>(IList<DynamicFilter> filters)
    {
        if (filters.Count == 0)
            return null;

        ParameterExpression param = Expression.Parameter(typeof(T), "t");
        Expression exp = null;

        if (filters.Count == 1)
        {
            exp = GetExpression<T>(param, filters[0]);
        }
        else if (filters.Count == 2)
        {
            exp = GetExpression<T>(param, filters[0], filters[1]);
        }
        else
        {
            while (filters.Count > 0)
            {
                var f1 = filters[0];
                var f2 = filters[1];

                exp = exp == null
                    ? GetExpression<T>(param, filters[0], filters[1])
                    : Expression.AndAlso(exp, GetExpression<T>(param, filters[0], filters[1]));

                filters.Remove(f1);
                filters.Remove(f2);

                if (filters.Count == 1)
                {
                    exp = Expression.AndAlso(exp, GetExpression<T>(param, filters[0]));
                    filters.RemoveAt(0);
                }
            }
        }

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

    private static Expression GetExpression<T>(ParameterExpression param, DynamicFilter filter)
    {
        MemberExpression member = Expression.Property(param, filter.PropertyName);
        ConstantExpression constant = Expression.Constant(filter.Value);

        return Expression.Equal(member, constant);
    }

    private static BinaryExpression GetExpression<T>(ParameterExpression param, DynamicFilter filter1, DynamicFilter filter2)
    {
        Expression bin1 = GetExpression<T>(param, filter1);
        Expression bin2 = GetExpression<T>(param, filter2);

        return Expression.AndAlso(bin1, bin2);
    }
}

public class DynamicFilter
{
    public string PropertyName { get; set; }
    public object Value { get; set; }
}


将其与您发布的代码一起使用:

    public static IQueryable<T> FilerByProperties(string properiesFilter, IQueryable<T> query)
    {
        if (properiesFilter == null) properiesFilter = "";
        string[] properties = properiesFilter.Split(";");

        var filters = new List<DynamicFilter>();
        for (int i = 0; i < properties.Length; i++)
        {
            if (!properiesFilter.IsNullOrEmpty())
            {
                int pocisionProp = properties[i].ToString().IndexOf('=');
                string prop = properties[i].Substring(0, pocisionProp);
                object value = properties[i].Substring(pocisionProp + 1);

                if (typeof(T).GetProperty(prop) != null)
                {
                    var badWayBuySomeWay = 0;
                    if(Int32.TryParse(value.ToString(), out badWayBuySomeWay))
                    {
                        value = badWayBuySomeWay;
                    }
                    var filter = new DynamicFilter { PropertyName = prop, Value = value };
                    filters.Add(filter);
                }
            }
        }

        if (filters.Count > 0)
        {
            var deleg = ExpressionBuilder.GetExpression<T>(filters).Compile();
            return query.Where(deleg).AsQueryable();
        }

        return query;
    }

关于c# - 按动态属性过滤,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59097131/

10-11 22:32
查看更多