我有一个动态过滤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/