如何在 orderby 子句中使用带有动态参数的 LINQ
how to use LINQ with dynamic paramters in orderby clause
我在使用 orderby linq
表达式中的动态参数时遇到问题
SearchExp 函数
public Expression<Func<EmailAflAwmMessageDM, bool>> SearchXpr(string param, string q)
{
if (param == "to")
return e => e.to_msg.Contains(q);
else if (param == "from")
return e => e.from_msg.Contains(q);
else if (param == "cc")
return e => e.cc_msg.Contains(q);
else if (param == "bcc")
return e => e.bcc_msg.Contains(q);
else if (param == "subject")
return e => e.subject.Contains(q);
else
return e => e.body_text.Contains(q);
}
filterExp 函数
public Expression<Func<EmailAflAwmMessageDM, bool>> FiltertXpr(string filter, string value)
{
if (filter == "attachments")
return e => e.attachments == value;
else if (filter == "flagged")
return e => e.flagged == value;
else
return e => e.seen == value;
}
IQueryable 函数
private IQueryable SearchFilter(string param,string q,string filter,
string value,string sort,string dir)
{
var searchXpr = SearchXpr(param, q);
var filterXpr = FiltertXpr(filter, value);
var emailmessage =
db.EmailAflAwmMessage.
Where(filterXpr).Where(searchXpr)
.OrderByDescending(a => a.msg_date).Select(a =>
new
{
a.subject,
a.msg_date,
});
return emailmessage;
}
以上代码有效,但我需要 OrderBy
动态方式。
因为我有 2 个参数 sort(表示它的参数名称)和 dir(表示升序或降序)就像我想要 orderby(参数名称)dir
请帮助我,感谢您宝贵的时间和建议,并建议我使用简单的方法进行任何替代。谢谢。
我建议您阅读有关 Expression's tree's 的内容,下面的代码用于教学,但我认为这会对您有所帮助:
public static class ExpressionBuilder
{
private static readonly MethodInfo ToStringMethod = typeof(object).GetMethod("ToString");
private static readonly MethodInfo StringContainsMethod = typeof(string).GetMethod("Contains");
public static Func<T, object> Selector<T>(string prop)
{
var type = typeof(T);
var param = Expression.Parameter(type);
return Expression.Lambda<Func<T, object>>(Expression.Property(param, type.GetProperty(prop)), param).Compile();
}
public static Expression<Func<T, bool>> BuildFilterPredicate<T>(string q)
{
var query = Expression.Constant(q);
var type = typeof(T);
var lbdSelector = Expression.Parameter(type);
var predicates = type.GetProperties().SelectMany(p => PredicateContainsBuilder(lbdSelector, p, query)).ToList();
Expression body = predicates[0];
body = predicates.Skip(1).Aggregate(body, Expression.OrElse);
return Expression.Lambda<Func<T, bool>>(body, lbdSelector);
}
private static IEnumerable<MethodCallExpression> PredicateContainsBuilder(Expression lbdSelector, PropertyInfo prop, Expression query)
{
if (prop.PropertyType.IsClass)
return new List<MethodCallExpression> { Expression.Call(Expression.Call(Expression.Property(lbdSelector, prop), ToStringMethod), StringContainsMethod, query) };
var properties = prop.PropertyType.GetProperties();
return properties.Select(p => Expression.Call(Expression.Call(Expression.Property(lbdSelector, p), ToStringMethod), StringContainsMethod, query)).ToList();
}
}
所以现在你在你的方法中这样做:
Note:
- I supose that the entity is EmailMessage so i use that to generate the predicate;
- It doesn't search in depth;
- it will search in all properties and doesn't use the
string param
to define what property to match;
private IQueryable SearchFilter(string param,string q,string filter,string value,string sort,string dir)
{
var emailMessage = db.EmailAflAwmMessage
.Where(ExpressionBuilder.BuildFilterPredicate<EmailMessage>(q))
.OrderBy(ExpressionBuilder.Selector<EmailMessage>(sort))
.Select(m=> new{m.subject,m.msg_date});
return emailmessage;
}
我找到了简单的解决方案,现在它与我合作,还有更多选择,但我只是分享我的答案:
SortXpr 函数
private IQueryable SortXpr(IQueryable<EmailAflAwmMessageDM> email ,string sort,string dir) {
if (sort.Contains("to"))
{
if (dir.Contains("asc"))
{
return email.OrderBy(e => e.to_msg);
}
else
{
return email.OrderByDescending(e => e.to_msg);
}
}
else if (sort.Contains("from"))
{
if (dir.Contains("asc"))
{
return email.OrderBy(e => e.from_msg);
}
else
{
return email.OrderByDescending(e => e.from_msg);
}
}
else if (sort.Contains("subject"))
{
if (dir.Contains("asc"))
{
return email.OrderBy(e => e.subject);
}
else
{
return email.OrderByDescending(e => e.subject);
}
}
else
{
if (dir.Contains("asc"))
{
return email.OrderBy(e => e.msg_date);
}
else
{
return email.OrderByDescending(e => e.msg_date);
}
}
}
FilterXpr 函数
private Expression<Func<EmailAflAwmMessageDM, bool>> FiltertXpr(string filter, string value)
{
if (filter == "attachments")
return e => e.attachments == value;
else if (filter == "flagged")
return e => e.flagged == value;
else
return e => e.seen == value;
}
SearchXpr 函数
private Expression<Func<EmailAflAwmMessageDM, bool>> SearchXpr(string param, string q)
{
if (param == "to")
return e => e.to_msg.Contains(q);
else if (param == "from")
return e => e.from_msg.Contains(q);
else if (param == "cc")
return e => e.cc_msg.Contains(q);
else if (param == "bcc")
return e => e.bcc_msg.Contains(q);
else if (param == "subject")
return e => e.subject.Contains(q);
else
return e => e.body_text.Contains(q);
}
SearchFilterCondition 函数
private IQueryable SearchFilterCondition(string param,string q
,string filter,string value,string sort,string dir)
{
var searchXpr = SearchXpr(param, q);
var filterXpr = FiltertXpr(filter, value);
IQueryable<EmailAflAwmMessageDM>
EmailAflAwmMessagejc = db.EmailAflAwmMessage.Where(filterXpr).Where(searchXpr);
return SortXpr(EmailAflAwmMessagejc, sort, dir);
}
感谢 Whosebug 社区,感谢您宝贵的时间,再次感谢。
我在使用 orderby linq
表达式中的动态参数时遇到问题
SearchExp 函数
public Expression<Func<EmailAflAwmMessageDM, bool>> SearchXpr(string param, string q) { if (param == "to") return e => e.to_msg.Contains(q); else if (param == "from") return e => e.from_msg.Contains(q); else if (param == "cc") return e => e.cc_msg.Contains(q); else if (param == "bcc") return e => e.bcc_msg.Contains(q); else if (param == "subject") return e => e.subject.Contains(q); else return e => e.body_text.Contains(q); }
filterExp 函数
public Expression<Func<EmailAflAwmMessageDM, bool>> FiltertXpr(string filter, string value) { if (filter == "attachments") return e => e.attachments == value; else if (filter == "flagged") return e => e.flagged == value; else return e => e.seen == value; }
IQueryable 函数
private IQueryable SearchFilter(string param,string q,string filter, string value,string sort,string dir) { var searchXpr = SearchXpr(param, q); var filterXpr = FiltertXpr(filter, value); var emailmessage = db.EmailAflAwmMessage. Where(filterXpr).Where(searchXpr) .OrderByDescending(a => a.msg_date).Select(a => new { a.subject, a.msg_date, }); return emailmessage; }
以上代码有效,但我需要 OrderBy
动态方式。
因为我有 2 个参数 sort(表示它的参数名称)和 dir(表示升序或降序)就像我想要 orderby(参数名称)dir
请帮助我,感谢您宝贵的时间和建议,并建议我使用简单的方法进行任何替代。谢谢。
我建议您阅读有关 Expression's tree's 的内容,下面的代码用于教学,但我认为这会对您有所帮助:
public static class ExpressionBuilder
{
private static readonly MethodInfo ToStringMethod = typeof(object).GetMethod("ToString");
private static readonly MethodInfo StringContainsMethod = typeof(string).GetMethod("Contains");
public static Func<T, object> Selector<T>(string prop)
{
var type = typeof(T);
var param = Expression.Parameter(type);
return Expression.Lambda<Func<T, object>>(Expression.Property(param, type.GetProperty(prop)), param).Compile();
}
public static Expression<Func<T, bool>> BuildFilterPredicate<T>(string q)
{
var query = Expression.Constant(q);
var type = typeof(T);
var lbdSelector = Expression.Parameter(type);
var predicates = type.GetProperties().SelectMany(p => PredicateContainsBuilder(lbdSelector, p, query)).ToList();
Expression body = predicates[0];
body = predicates.Skip(1).Aggregate(body, Expression.OrElse);
return Expression.Lambda<Func<T, bool>>(body, lbdSelector);
}
private static IEnumerable<MethodCallExpression> PredicateContainsBuilder(Expression lbdSelector, PropertyInfo prop, Expression query)
{
if (prop.PropertyType.IsClass)
return new List<MethodCallExpression> { Expression.Call(Expression.Call(Expression.Property(lbdSelector, prop), ToStringMethod), StringContainsMethod, query) };
var properties = prop.PropertyType.GetProperties();
return properties.Select(p => Expression.Call(Expression.Call(Expression.Property(lbdSelector, p), ToStringMethod), StringContainsMethod, query)).ToList();
}
}
所以现在你在你的方法中这样做:
Note:
- I supose that the entity is EmailMessage so i use that to generate the predicate;
- It doesn't search in depth;
- it will search in all properties and doesn't use the
string param
to define what property to match;
private IQueryable SearchFilter(string param,string q,string filter,string value,string sort,string dir)
{
var emailMessage = db.EmailAflAwmMessage
.Where(ExpressionBuilder.BuildFilterPredicate<EmailMessage>(q))
.OrderBy(ExpressionBuilder.Selector<EmailMessage>(sort))
.Select(m=> new{m.subject,m.msg_date});
return emailmessage;
}
我找到了简单的解决方案,现在它与我合作,还有更多选择,但我只是分享我的答案:
SortXpr 函数
private IQueryable SortXpr(IQueryable<EmailAflAwmMessageDM> email ,string sort,string dir) { if (sort.Contains("to")) { if (dir.Contains("asc")) { return email.OrderBy(e => e.to_msg); } else { return email.OrderByDescending(e => e.to_msg); } } else if (sort.Contains("from")) { if (dir.Contains("asc")) { return email.OrderBy(e => e.from_msg); } else { return email.OrderByDescending(e => e.from_msg); } } else if (sort.Contains("subject")) { if (dir.Contains("asc")) { return email.OrderBy(e => e.subject); } else { return email.OrderByDescending(e => e.subject); } } else { if (dir.Contains("asc")) { return email.OrderBy(e => e.msg_date); } else { return email.OrderByDescending(e => e.msg_date); } } }
FilterXpr 函数
private Expression<Func<EmailAflAwmMessageDM, bool>> FiltertXpr(string filter, string value) { if (filter == "attachments") return e => e.attachments == value; else if (filter == "flagged") return e => e.flagged == value; else return e => e.seen == value; }
SearchXpr 函数
private Expression<Func<EmailAflAwmMessageDM, bool>> SearchXpr(string param, string q) { if (param == "to") return e => e.to_msg.Contains(q); else if (param == "from") return e => e.from_msg.Contains(q); else if (param == "cc") return e => e.cc_msg.Contains(q); else if (param == "bcc") return e => e.bcc_msg.Contains(q); else if (param == "subject") return e => e.subject.Contains(q); else return e => e.body_text.Contains(q); }
SearchFilterCondition 函数
private IQueryable SearchFilterCondition(string param,string q ,string filter,string value,string sort,string dir) { var searchXpr = SearchXpr(param, q); var filterXpr = FiltertXpr(filter, value); IQueryable<EmailAflAwmMessageDM> EmailAflAwmMessagejc = db.EmailAflAwmMessage.Where(filterXpr).Where(searchXpr); return SortXpr(EmailAflAwmMessagejc, sort, dir); }
感谢 Whosebug 社区,感谢您宝贵的时间,再次感谢。