C# Linq OrderBy 过滤空值或空值到最后
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13604630/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# Linq OrderBy filtering null or empty values to be last
提问by Cihan Uygun
I try to make my custom orderby extension method, i successfully worked my code but in addition i want to list null or empty or zero values last in result, anyone can help me about that issue ?
我尝试制作我的自定义 orderby 扩展方法,我成功地运行了我的代码,但此外我想在结果中最后列出空值或空值或零值,任何人都可以帮助我解决这个问题吗?
Here is my extension method to orderby
这是我对orderby的扩展方法
public static IQueryable<T> OrderBy<T>(this IQueryable<T> 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<T>(mce);
}
Thanks in advance
提前致谢
采纳答案by Dave Anson
Without using an extension method....
不使用扩展方法....
Create a custom IComparer<string>to check the empty values before using the default String.Compare. The first checks will return -1 instead of 1 or 1 instead of -1, if using the standard string comparison.
创建自定义IComparer<string>以在使用默认值之前检查空值String.Compare。如果使用标准字符串比较,第一次检查将返回 -1 而不是 1 或 1 而不是 -1。
/// <summary>
/// Returns -1 instead of 1 if y is IsNullOrEmpty when x is Not.
/// </summary>
public class EmptyStringsAreLast : IComparer<string>
{
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);
}
}
}
Pass your EmptyStringsAreLastcomparer into the OrderByof Lambda expression. In this solution teams who have entered the race should appear alphabetical order, but the unaffiliated race entries should appear at then end.
将您的EmptyStringsAreLast比较器传递到OrderByLambda 表达式中。在此解决方案中,已参加比赛的团队应按字母顺序显示,但非附属比赛条目应显示在最后。
var entries = repository.Race.Where(e => e.EventId == id)
.OrderBy(e => e.TeamName, new EmptyStringsAreLast())
.ThenBy(e => e.LastName)
.ThenBy(e => e.FirstName);
回答by Rajes
The simplest way is to use
最简单的方法是使用
OrderBy(e => String.IsNullOrEmpty(e.TeamName)
This doesn't require any extension method or custom IComparerimplementation etc.
这不需要任何扩展方法或自定义IComparer实现等。
var entries = repository.Race.Where(e => e.EventId == id)
.OrderBy(e => String.IsNullOrEmpty(e.TeamName))
.ThenBy(e => e.LastName)
.ThenBy(e => e.FirstName);
回答by aukinfo
This answer is perhaps what you were originally looking for - using your generic extension method:
这个答案可能是您最初寻找的 - 使用您的通用扩展方法:
public static IQueryable<T> OrderByFieldNullsLast<T>(this IQueryable<T> q, string SortField, bool Ascending)
{
//We are rebuilding .OrderByDescending(p => p.SortField.HasValue).ThenBy(p => p.SortField)
//i.e. 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<T>(ThenByCallExpression);
}
回答by Alexander - Reinstate Monica
Building on Dave Anson'sanswer, you can user Comparer.Create()to create the Comparer from a lambda. Here's an example that sorts unsortedby its myStringstring fields, with nullor empty strings appearing last.
基于Dave Anson 的回答,您可以使用Comparer.Create()从 lambda 创建比较器。这是一个unsorted按myString字符串字段排序的示例,null最后出现的是 或 空字符串。
var sorted = unsorted.OrderBy(x => x.myString, Comparer<string>.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);
}))
(To put them first, switch the signs on the 1constants)
(把它们放在第一位,切换1常数上的符号)
回答by Arphenon
it works for me:
这个对我有用:
private static IQueryable<T> GetOrderQuery<T>(this IQueryable<T> q, BaseFilterCollection filter)
{
q = q.OrderBy(GetExpression<T>(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<T>(rs);
}
private static Expression<Func<T, bool>> GetExpression<T>(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<Func<T, bool>>(exp, param);
}

