How to dynamically build Where Expression expression in Entity Framework?

I reviewed this answer on how to dynamically create an OrderBy expression in the Entity Framework. But I would also like to create a dynamic Where expression. Something like that:

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; } 

Passing properties for filtering and values ​​as an entity. Queryable has two methods for where both take two parameters, so I'm not even sure which one is correct.

And at that moment I’m a little lost. I'm not sure how to reorganize the original OrderByProerty method to provide WhereByProperty . I know that I'm completely wrong here. I'm not sure what to do with this.

Ideally, I would like to expand it even more by providing a collection of objects that can be used to build a query with operators and and or .. p>

+4
source share
2 answers

Queryable has two methods for where both take two parameters, so I'm not even sure which one is correct.

You need one that gets Expression<Func<T, bool>> predicate .

Here's how you can dynamically build a predicate similar to (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); } } 

I tried to write it in such a way that you can step over the code to understand what it does. The only line that may be required to explain:

 var memberValue = member.Split('.').Aggregate((Expression)item, Expression.PropertyOrField); 

This is an easy way to handle nested properties like obj.Prop1.Prop2 , etc. If you do not need such features, you can simply use this:

 var memberValue = Expression.PropertyOrField(item, member); 
+3
source

I don't need nested properties (for now). I changed your code a little and it works for me:

  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); } 
+1
source

Source: https://habr.com/ru/post/1246033/


All Articles