问题描述
我正在使用Dynamic Linq来订购结果集,具体取决于传递哪个列.当用户单击表列时,我正在使用它来订购表.
如果属性IM订购是一个null的类,代码掉落了,我希望能够动态订购字符串,但如果属性为类,则适合nulls.
.这是system.linq.dynamic class im使用的代码.
public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values) { if (source == null) { throw new ArgumentNullException("source"); } if (ordering == null) { throw new ArgumentNullException("ordering"); } ParameterExpression[] parameters = new ParameterExpression[1] { Expression.Parameter(source.ElementType, "") }; IEnumerable<DynamicOrdering> enumerable = new ExpressionParser( parameters, ordering, values).ParseOrdering(); Expression expression = source.Expression; string str1 = "OrderBy"; string str2 = "OrderByDescending"; foreach (DynamicOrdering dynamicOrdering in enumerable) { expression = (Expression) Expression.Call(typeof (Queryable), dynamicOrdering.Ascending ? str1 : str2, new Type[2] { source.ElementType, dynamicOrdering.Selector.Type }, new Expression[2] { expression, (Expression) Expression.Quote((Expression) Expression.Lambda( dynamicOrdering.Selector, parameters)) }); str1 = "ThenBy"; str2 = "ThenByDescending"; } return source.Provider.CreateQuery(expression); }
并像这样称呼它
if (property.PropertyType == typeof(Sitecore.Data.Items.Item)) { orderByProperty = property.Name + ".Name"; } else { orderByProperty = property.Name; } return tableOrder == TableOrder.az ? projects.OrderBy(orderByProperty + " ascending").ToList() : projects.OrderBy(orderByProperty + " descending").ToList();
属性有时是一类,如果是这种情况,我希望能够通过类上的名称订购.以上代码有效,但是如果属性是类,则属于null.
我该如何按字段订购并在末尾进行空项目?
推荐答案
我找到了答案.用以下内容替换system.linq.dynamic.dynamicqueryable类中的OrderBy查询.它将处理为对象的属性中的nulls.
public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values) { //This handles nulls in a complex object var orderingSplit = ordering.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries); var sortField = orderingSplit[0]; var splitted_sortField = sortField.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries); if (splitted_sortField.Length > 1) { sortField = "iif(" + splitted_sortField[0] + "==null,null," + sortField + ")"; } ordering = orderingSplit.Length == 2 ? sortField + " " + orderingSplit[1] : sortField; if (source == null) throw new ArgumentNullException("source"); if (ordering == null) throw new ArgumentNullException("ordering"); ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter(source.ElementType, "") }; ExpressionParser parser = new ExpressionParser(parameters, ordering, values); IEnumerable<DynamicOrdering> orderings = parser.ParseOrdering(); Expression queryExpr = source.Expression; string methodAsc = "OrderBy"; string methodDesc = "OrderByDescending"; foreach (DynamicOrdering o in orderings) { queryExpr = Expression.Call( typeof(Queryable), o.Ascending ? methodAsc : methodDesc, new Type[] { source.ElementType, o.Selector.Type }, queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters))); methodAsc = "ThenBy"; methodDesc = "ThenByDescending"; } return source.Provider.CreateQuery(queryExpr); }
从此处获取代码并将其直接烘烤到动态LINQ函数中.
问题描述
I'm using dynamic Linq to order a result set depending on which column is passed in. I'm using this to order a table when a user clicks on a table column.
If the property im ordering on is a class which is null the code falls over, i want to be able to dynamically orderby a string but cater for nulls if the property is a class.
This is the code from the System.Linq.Dynamic class im using.
public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values) { if (source == null) { throw new ArgumentNullException("source"); } if (ordering == null) { throw new ArgumentNullException("ordering"); } ParameterExpression[] parameters = new ParameterExpression[1] { Expression.Parameter(source.ElementType, "") }; IEnumerable<DynamicOrdering> enumerable = new ExpressionParser( parameters, ordering, values).ParseOrdering(); Expression expression = source.Expression; string str1 = "OrderBy"; string str2 = "OrderByDescending"; foreach (DynamicOrdering dynamicOrdering in enumerable) { expression = (Expression) Expression.Call(typeof (Queryable), dynamicOrdering.Ascending ? str1 : str2, new Type[2] { source.ElementType, dynamicOrdering.Selector.Type }, new Expression[2] { expression, (Expression) Expression.Quote((Expression) Expression.Lambda( dynamicOrdering.Selector, parameters)) }); str1 = "ThenBy"; str2 = "ThenByDescending"; } return source.Provider.CreateQuery(expression); }
and calling it like this
if (property.PropertyType == typeof(Sitecore.Data.Items.Item)) { orderByProperty = property.Name + ".Name"; } else { orderByProperty = property.Name; } return tableOrder == TableOrder.az ? projects.OrderBy(orderByProperty + " ascending").ToList() : projects.OrderBy(orderByProperty + " descending").ToList();
the property is sometimes a class, if this is the case i want to be able to order it by a field called name on the class. The above code works but if the property is a class and null then it falls over.
How do I order by a field and have the null items at the end?
推荐答案
I've found the answer. Replace the OrderBy query in the System.Linq.Dynamic.DynamicQueryable class with the below. It will handle nulls in a property that is an object.
public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values) { //This handles nulls in a complex object var orderingSplit = ordering.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries); var sortField = orderingSplit[0]; var splitted_sortField = sortField.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries); if (splitted_sortField.Length > 1) { sortField = "iif(" + splitted_sortField[0] + "==null,null," + sortField + ")"; } ordering = orderingSplit.Length == 2 ? sortField + " " + orderingSplit[1] : sortField; if (source == null) throw new ArgumentNullException("source"); if (ordering == null) throw new ArgumentNullException("ordering"); ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter(source.ElementType, "") }; ExpressionParser parser = new ExpressionParser(parameters, ordering, values); IEnumerable<DynamicOrdering> orderings = parser.ParseOrdering(); Expression queryExpr = source.Expression; string methodAsc = "OrderBy"; string methodDesc = "OrderByDescending"; foreach (DynamicOrdering o in orderings) { queryExpr = Expression.Call( typeof(Queryable), o.Ascending ? methodAsc : methodDesc, new Type[] { source.ElementType, o.Selector.Type }, queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters))); methodAsc = "ThenBy"; methodDesc = "ThenByDescending"; } return source.Provider.CreateQuery(queryExpr); }
Taken the code from here and baked it directly into the Dynamic Linq function.