我正在任何列/字段映射的查询中为searchText寻找通用过滤器
public static IQueryable<T> Filter<T>(this IQueryable<T> source, string searchTerm)
{
var propNames = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(e=>e.PropertyType == typeof(String)).Select(x => x.Name).ToArray();
//I am getting the property names but How can I create Expression for
source.Where(Expression)
}
这里我给你一个例子
现在,从Asp.net MVC4中的HTML5表中,我提供了一个搜索框来过滤输入文本的结果,该结果可以匹配以下任何列/菜单类属性值,我想在服务器端进行此搜索,如何我可以实现它吗?
EF模型类别
public partial class Menu
{
public int Id { get; set; }
public string MenuText { get; set; }
public string ActionName { get; set; }
public string ControllerName { get; set; }
public string Icon { get; set; }
public string ToolTip { get; set; }
public int RoleId { get; set; }
public virtual Role Role { get; set; }
}
最佳答案
void Main()
{
// creates a clause like
// select * from Menu where MenuText like '%ASD%' or ActionName like '%ASD%' or....
var items = Menu.Filter("ASD").ToList();
}
// Define other methods and classes here
public static class QueryExtensions
{
public static IQueryable<T> Filter<T>(this IQueryable<T> query, string search)
{
var properties = typeof(T).GetProperties().Where(p =>
/*p.GetCustomAttributes(typeof(System.Data.Objects.DataClasses.EdmScalarPropertyAttribute),true).Any() && */
p.PropertyType == typeof(String));
var predicate = PredicateBuilder.False<T>();
foreach (var property in properties )
{
predicate = predicate.Or(CreateLike<T>(property,search));
}
return query.AsExpandable().Where(predicate);
}
private static Expression<Func<T,bool>> CreateLike<T>( PropertyInfo prop, string value)
{
var parameter = Expression.Parameter(typeof(T), "f");
var propertyAccess = Expression.MakeMemberAccess(parameter, prop);
var like = Expression.Call(propertyAccess, "Contains", null, Expression.Constant(value,typeof(string)));
return Expression.Lambda<Func<T, bool>>(like, parameter);
}
}
您需要添加对LinqKit的引用才能使用PredicateBuilder和AsExpandable方法
否则,将不适用于EF,仅适用于Linq to SQL
如果要
Col1 like '%ASD%' AND Col2 like '%ASD%' et
,请将PredicateBuilder.False
更改为PredicateBuilder.True
,将predicate.Or
更改为predicate.And
另外,您还需要找到一种通过自己的自定义属性来区分映射属性的方法(例如,在部分类中定义)