C#Linq OrderBy过滤null或空值为last

我尝试使用自定义orderby扩展方法,我成功地处理了我的代码,但另外我想在结果中列出null或空值或零值,任何人都可以帮我解决这个问题?

这是我对orderby的扩展方法

public static IQueryable OrderBy(this IQueryable q, string SortField, bool isAsc) { //var nullExpr = Expression.Constant(null, typeof(T)); var param = Expression.Parameter(typeof(T), "p"); var prop = Expression.Property(param, SortField); var exp = Expression.Lambda(prop, param); string method = isAsc ? "OrderBy" : "OrderByDescending"; Type[] types = new Type[] { q.ElementType, exp.Body.Type }; var mce = Expression.Call(typeof(Queryable), method, types, q.Expression, exp); return q.Provider.CreateQuery(mce); } 

提前致谢

不使用扩展方法….

在使用默认String.Compare之前,创建自定义IComparer以检查空值。 如果使用标准字符串比较,则第一次检查将返回-1而不是1或1而不是-1。

 ///  /// Returns -1 instead of 1 if y is IsNullOrEmpty when x is Not. ///  public class EmptyStringsAreLast : IComparer { public int Compare(string x, string y) { if (String.IsNullOrEmpty(y) && !String.IsNullOrEmpty(x)) { return -1; } else if (!String.IsNullOrEmpty(y) && String.IsNullOrEmpty(x)) { return 1; } else { return String.Compare(x, y); } } } 

EmptyStringsAreLast比较器传递给Lambda表达式的OrderBy 。 在此解决方案中,参加比赛的团队应按字母顺序排列,但非关联竞赛条目应在结束时出现。

 var entries = repository.Race.Where(e => e.EventId == id) .OrderBy(e => e.TeamName, new EmptyStringsAreLast()) .ThenBy(e => e.LastName) .ThenBy(e => e.FirstName); 

最简单的方法是使用

 OrderBy(e => String.IsNullOrEmpty(e.TeamName) 

这不需要任何扩展方法或自定义IComparer实现等。

 var entries = repository.Race.Where(e => e.EventId == id) .OrderBy(e => String.IsNullOrEmpty(e.TeamName)) .ThenBy(e => e.LastName) .ThenBy(e => e.FirstName); 

这个答案可能就是你最初想要的 – 使用你的通用扩展方法:

  public static IQueryable OrderByFieldNullsLast(this IQueryable q, string SortField, bool Ascending) { //We are rebuilding .OrderByDescending(p => p.SortField.HasValue).ThenBy(p => p.SortField) //ie sort first by whether sortfield has a value, then by sortfield asc or sortfield desc //create the expression tree that represents the generic parameter to the predicate var param = Expression.Parameter(typeof(T), "p"); //create an expression tree that represents the expression p=>p.SortField.HasValue var prop = Expression.Property(param, SortField); var hasValue = Expression.Property(prop, "HasValue"); var exp = Expression.Lambda(hasValue, param); string method = "OrderByDescending"; Type[] types = new Type[] { q.ElementType, exp.Body.Type }; var orderByCallExpression = Expression.Call(typeof(Queryable), method, types, q.Expression, exp); //now do the ThenBy bit,sending in the above expression to the Expression.Call exp = Expression.Lambda(prop, param); types = new Type[] { q.ElementType, exp.Body.Type }; method = Ascending ? "ThenBy" : "ThenByDescending"; var ThenByCallExpression = Expression.Call(typeof(Queryable), method, types,orderByCallExpression, exp); return q.Provider.CreateQuery(ThenByCallExpression); } 

基于Dave Anson的回答,您可以使用Comparer.Create()从lambda创建Comparer。 这是一个通过myString字符串字段排序unsorted的示例,最后出现空字符串或空字符串。

 var sorted = unsorted.OrderBy(x => x.myString, Comparer.Create((x, y) => { if ( string.IsNullOrEmpty(y) && !string.IsNullOrEmpty(x)) return -1; else if (!string.IsNullOrEmpty(y) && string.IsNullOrEmpty(x)) return +1; else return string.Compare(x, y); })) 

(把它们放在第一位,在1常数上切换标志)

这个对我有用:

  private static IQueryable GetOrderQuery(this IQueryable q, BaseFilterCollection filter) { q = q.OrderBy(GetExpression(filter.SortField)); var param = Expression.Parameter(typeof(T), "p"); var prop = Expression.Property(param, filter.SortField); var exp = Expression.Lambda(prop, param); string method = filter.SortDirection == SortDirectionType.Asc ? "ThenBy" : "ThenByDescending"; Type[] types = { q.ElementType, exp.Body.Type }; var rs = Expression.Call(typeof(Queryable), method, types, q.Expression, exp); return q.Provider.CreateQuery(rs); } private static Expression> GetExpression(string sortField) { ParameterExpression param = Expression.Parameter(typeof(T), "p"); Expression prop = Expression.Property(param, sortField); var info = typeof(T).GetProperty(sortField, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); Expression exp = Expression.Equal(prop, info.PropertyType.IsValueType ? Expression.Constant(Activator.CreateInstance(info.PropertyType)) : Expression.Constant(null)); return Expression.Lambda>(exp, param); }