我已经了解了this answer如何在Entity Framework中动态创建OrderBy表达式。但是我也想建立一个动态的Where表达式。有点像这样:
public IEnumerable<InventoryItem> GetAll(string filterBy, object value)
{
var results = new List<InventoryItem>();
using (var db = new InventoryDb())
{
if (QueryHelper.PropertyExists<InventoryItem>(filterBy))
{
var query = db.rri_InventoryItems.WhereByProperty(filterBy, value);
foreach(var item in query.Where(expr))
{
results.Add(ConvertItem(item));
}
}
}
return results;
}
传入属性以过滤by和值作为ab对象。 Queryable有两种方法,哪里都有两个参数,所以我甚至不确定哪一个是正确的。
此时此刻我失去了一点点。我不确定如何重构原始 OrderByProerty 方法以提供 WhereByProperty 。我知道我在这里完全错了。我不知道该怎么做。
理想情况下,我希望通过提供可用于使用 ands 和或运算符构建查询的对象集合来进一步扩展此功能。
答案 0 :(得分:6)
Queryable有两种方法,哪里都有两个参数,所以我甚至不确定哪一个是正确的。
您需要收到Expression<Func<T, bool>> predicate
的人。
以下是如何动态构建类似于(T item) => item.Property == value
的谓词:
public static partial class QueryableExtensions
{
public static IQueryable<T> WhereEquals<T>(this IQueryable<T> source, string member, object value)
{
var item = Expression.Parameter(typeof(T), "item");
var memberValue = member.Split('.').Aggregate((Expression)item, Expression.PropertyOrField);
var memberType = memberValue.Type;
if (value != null && value.GetType() != memberType)
value = Convert.ChangeType(value, memberType);
var condition = Expression.Equal(memberValue, Expression.Constant(value, memberType));
var predicate = Expression.Lambda<Func<T, bool>>(condition, item);
return source.Where(predicate);
}
}
我试图以这样的方式编写它,以便您可以跳过代码以了解它的作用。可能需要解释的唯一一行是:
var memberValue = member.Split('.').Aggregate((Expression)item, Expression.PropertyOrField);
这是一种处理obj.Prop1.Prop2
等嵌套属性的简单方法。如果您不需要这样的功能,可以简单地使用它:
var memberValue = Expression.PropertyOrField(item, member);
答案 1 :(得分:1)
我还不需要嵌套属性。我稍微修改了你的代码并使其正常工作:
public static IQueryable<T> WhereEquals<T>(
this IQueryable<T> source, string propertyName, object value)
{
if (typeof(T).GetProperty(propertyName, BindingFlags.IgnoreCase |
BindingFlags.Public | BindingFlags.Instance) == null)
{
return null;
}
ParameterExpression parameter = Expression.Parameter(typeof(T), "item");
Expression whereProperty = Expression.Property(parameter, propertyName);
Expression constant = Expression.Constant(value);
Expression condition = Expression.Equal(whereProperty, constant);
Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(condition,parameter);
return source.Where(lambda);
}