C#Linq OrderBy过滤最后一个为null或空的值

C#Linq OrderBy过滤最后一个为null或空的值,c#,linq,expression,C#,Linq,Expression,我尝试创建我的自定义orderby扩展方法,我成功地处理了我的代码,但除此之外,我想在结果中最后列出null、空或零值,有人能帮我解决这个问题吗 这是我对orderby的扩展方法 public static IQueryable<T> OrderBy<T>(this IQueryable<T> q, string SortField, bool isAsc) { //var nullExpr = Expression.Const

我尝试创建我的自定义orderby扩展方法,我成功地处理了我的代码,但除此之外,我想在结果中最后列出null、空或零值,有人能帮我解决这个问题吗

这是我对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);
    }
公共静态IQueryable OrderBy(此IQueryable q,字符串SortField,bool isAsc)
{
//var nullExpr=Expression.Constant(null,typeof(T));
var param=表达式参数(类型(T),“p”);
var prop=Expression.Property(param,SortField);
var exp=表达式Lambda(prop,param);
string method=isAsc?“OrderBy”:“OrderByDescending”;
类型[]类型=新类型[]{q.ElementType,exp.Body.Type};
var mce=Expression.Call(typeof(Queryable)、方法、类型、q.Expression、exp);
返回q.Provider.CreateQuery(mce);
}

提前感谢

无需使用扩展方法

在使用默认的
字符串之前,创建一个自定义的
i比较程序
,以检查空值。比较
。如果使用标准字符串比较,第一次检查将返回-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);
            }
        }
 }

最简单的方法是使用

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<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);
    }
public static IQueryable OrderByFieldNullsLast(此IQueryable q,字符串SortField,bool升序)
{
//我们正在重建.OrderByDescending(p=>p.SortField.HasValue),然后重建(p=>p.SortField)
//i、 e.首先按sortfield是否有值排序,然后按sortfield asc或sortfield desc排序
//创建表示谓词的泛型参数的表达式树
var param=表达式参数(类型(T),“p”);
//创建表示表达式p=>p.SortField.HasValue的表达式树
var prop=Expression.Property(param,SortField);
var hasValue=Expression.Property(prop,“hasValue”);
var exp=表达式Lambda(hasValue,param);
string方法=“OrderByDescending”;
类型[]类型=新类型[]{q.ElementType,exp.Body.Type};
var orderByCallExpression=Expression.Call(typeof(Queryable),方法,类型,q.Expression,exp);
//现在执行ThenBy位,将上面的表达式发送到表达式。调用
exp=表达式Lambda(prop,param);
types=新类型[]{q.ElementType,exp.Body.Type};
方法=上升?“然后下降”:“然后下降”;
var ThenByCallExpression=Expression.Call(typeof(Queryable),方法,类型,orderByCallExpression,exp);
返回q.Provider.CreateQuery(然后返回ByCallExpression);
}
基于answer,您可以使用户从lambda创建比较器。下面是一个示例,它通过
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);
    }))
var sorted=unsorted.OrderBy(x=>x.myString,Comparer.Create((x,y)=>{
if(string.IsNullOrEmpty(y)和&!string.IsNullOrEmpty(x))返回-1;
如果(!string.IsNullOrEmpty(y)和&string.IsNullOrEmpty(x))返回+1;
else返回字符串。比较(x,y);
}))
(首先,在
1
常量上切换符号)

这对我很有用:

    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);
    }
private静态IQueryable GetOrderQuery(此IQueryable q、BaseFilterCollection筛选器)
{
q=q.OrderBy(GetExpression(filter.SortField));
var param=表达式参数(类型(T),“p”);
var prop=Expression.Property(param,filter.SortField);
var exp=表达式Lambda(prop,param);
字符串方法=filter.SortDirection==SortDirectionType.Asc?“ThenBy”:“ThenBy Descending”;
Type[]types={q.ElementType,exp.Body.Type};
var rs=Expression.Call(typeof(Queryable),方法,类型,q.Expression,exp);
返回q.Provider.CreateQuery(rs);
}
私有静态表达式GetExpression(字符串sortField)
{
ParameterExpression param=表达式参数(typeof(T),“p”);
Expression prop=Expression.Property(param,sortField);
var info=typeof(T).GetProperty(sortField,BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
表达式exp=Expression.Equal(prop,info.PropertyType.IsValueType
?Expression.Constant(Activator.CreateInstance(info.PropertyType))
:Expression.Constant(null));
返回表达式.Lambda(exp,param);
}

你不需要复杂化,最简单的方法是这样做:

YourList.OrderByDescending(x => string.IsNullOrEmpty(x.value)
使用OrderByDescending或OrderBy,具体取决于您希望在开头还是结尾看到空字符串


关于

,但为此,您必须添加
。然后再添加(e=>e.TeamName)
.OrderBy(e=>String.IsNullOrEmpty(e.TeamName))
将只按布尔结果排序,而不按内容本身排序。不确定这为什么不是可接受的答案!看起来很完美!谢谢
YourList.OrderByDescending(x => string.IsNullOrEmpty(x.value)