C# 按动态特性筛选

C# 按动态特性筛选,c#,linq,C#,Linq,我有一种动态过滤列表的通用方法,我最近将我的项目更新为NetCore 3.0,之后该方法就不起作用了 这是我在调用方法时得到的错误 System.InvalidOperationException: 'The LINQ expression 'Where<Provincia>( source: OrderBy<Provincia, string>( source: DbSet<Provincia>, keySelect

我有一种动态过滤
列表
的通用方法,我最近将我的项目更新为
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.'

System.invalidoOperationException:“LINQ表达式”其中(
资料来源:OrderBy(
资料来源:DbSet,
键选择器:(p)=>p.identificator),
谓词:(p)=>p.GetType().GetProperty((未处理的参数:_prop_0)).GetValue(
对象:(对象)p,
索引:null)。无法转换ToString()=(未处理的参数:_值_1))'。以可以翻译的形式重写查询,或者通过插入对AsEnumerable()、AsAsAsAsyncEnumerable()、ToList()或ToListSync()的调用显式切换到客户端计算。看见https://go.microsoft.com/fwlink/?linkid=2101038 了解更多信息。”
这是我的方法

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静态IQueryable filerbyproperty(字符串属性过滤器,IQueryable查询)
{
如果(properiesFilter==null)properiesFilter=“”;
string[]properties=propertiesfilter.Split(“;”);
for(int i=0;ix.GetType().GetProperty(prop).GetValue(x,null).ToString()==value);
}
}
}
返回查询;
}
我就是这样用的

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);
}
公共覆盖任务GetAllAsync(PagedAndSortedRequest输入)
{
var lista=新列表();
var query=Repository.GetAllIncluding(x=>x.Pais);
query=CreateFilteredQuery(输入);
查询=应用排序(查询,输入);
query=FilterHelper.FilerByProperties(input.FilterProperties,查询);
lista=查询
.Skip(输入.SkipCount)
.Take(input.MaxResultCount)
.ToList();
var result=new PagedResultDto(query.Count(),ObjectMapper.Map(lista));
返回Task.FromResult(结果);
}
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; }
}
公共静态类ExpressionBuilder
{
公共静态表达式GetExpression(IList筛选器)
{
如果(filters.Count==0)
返回null;
ParameterExpression param=表达式参数(typeof(T),“T”);
表达式exp=null;
如果(filters.Count==1)
{
exp=GetExpression(参数,过滤器[0]);
}
else if(filters.Count==2)
{
exp=GetExpression(参数,过滤器[0],过滤器[1]);
}
其他的
{
而(filters.Count>0)
{
var f1=过滤器[0];
var f2=过滤器[1];
exp=exp==null
?GetExpression(参数、筛选器[0]、筛选器[1])
:Expression.AndAlso(exp,GetExpression(param,filters[0],filters[1]);
过滤器。移除(f1);
过滤器。移除(f2);
如果(filters.Count==1)
{
exp=Expression.AndAlso(exp,GetExpression(param,filters[0]);
过滤器。移除(0);
}
}
}
返回表达式.Lambda(exp,param);
}
私有静态表达式GetExpression(ParameterExpression param,DynamicFilter筛选器)
{
MemberExpression member=Expression.Property(param,filter.PropertyName);
ConstantPression常数=表达式常数(filter.Value);
返回表达式.Equal(成员,常量);
}
私有静态二进制表达式GetExpression(ParameterExpression param、DynamicFilter filter1、DynamicFilter filter2)
{
表达式bin1=GetExpression(参数,过滤器1);
表达式bin2=GetExpression(参数,过滤器2);
返回表达式.AndAlso(bin1,bin2);
}
}
公共类动态过滤器
{
公共字符串PropertyName{get;set;}
公共对象值{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;
    }
public静态IQueryable filerbyproperty(字符串属性过滤器,IQueryable查询)
{
如果(properiesFilter==null)properiesFilter=“”;
string[]properties=propertiesfilter.Split(“;”);
var filters=新列表();
for(int i=0;i0)
{
var deleg=ExpressionBuilder.GetExpression(filters.Compile();
返回query.Where(deleg.AsQueryable();
}
返回查询;
}

错误消息包含一个指向某些文档的链接,这些文档非常全面地描述了正在发生的事情,并建议您可以对此采取一些措施。我已经实现了您的解决方案