C# 带排序的动态Linq查询,末尾为空
我正在尝试构建一个ASP.NET页面,该页面在可空字段上排序。我想做的是,如果sortable字段中有空值,总是将这些行抛出到列表的末尾。否则,它们会显示在列表的开头,我可以想象在进入A-Z排序元素之前,页面和空值行页面 我在ASP.NET框架中工作。可排序列的解决方案是针对以下GridViewDataSource构建动态查询:C# 带排序的动态Linq查询,末尾为空,c#,asp.net,linq,sorting,dynamic-linq,C#,Asp.net,Linq,Sorting,Dynamic Linq,我正在尝试构建一个ASP.NET页面,该页面在可空字段上排序。我想做的是,如果sortable字段中有空值,总是将这些行抛出到列表的末尾。否则,它们会显示在列表的开头,我可以想象在进入A-Z排序元素之前,页面和空值行页面 我在ASP.NET框架中工作。可排序列的解决方案是针对以下GridViewDataSource构建动态查询: public static class QueryExtensions { public static IQueryable<T> SortBy<T&
public static class QueryExtensions {
public static IQueryable<T> SortBy<T>(this IQueryable<T> source, string propertyName) {
if (source == null) {
throw new ArgumentNullException("source");
}
// DataSource control passes the sort parameter with a direction
// if the direction is descending
int descIndex = propertyName.IndexOf(" DESC");
if (descIndex >= 0) {
propertyName = propertyName.Substring(0, descIndex).Trim();
}
if (String.IsNullOrEmpty(propertyName)) {
return source;
}
ParameterExpression parameter = Expression.Parameter(source.ElementType, String.Empty);
MemberExpression property = Expression.Property(parameter, propertyName);
LambdaExpression lambda = Expression.Lambda(property, parameter);
string methodName = (descIndex < 0) ? "OrderBy" : "OrderByDescending";
Expression methodCallExpression = Expression.Call(typeof(Queryable), methodName,
new Type[] { source.ElementType, property.Type },
source.Expression, Expression.Quote(lambda));
return source.Provider.CreateQuery<T>(methodCallExpression);
}
公共静态类查询扩展{
公共静态IQueryable排序方式(此IQueryable源,字符串propertyName){
if(source==null){
抛出新的ArgumentNullException(“源”);
}
//DataSource控件传递带有方向的sort参数
//如果方向是下降的
int descIndex=propertyName.IndexOf(“DESC”);
如果(描述索引>=0){
propertyName=propertyName.Substring(0,descIndex.Trim();
}
if(String.IsNullOrEmpty(propertyName)){
返回源;
}
ParameterExpression参数=Expression.parameter(source.ElementType,String.Empty);
MemberExpression属性=Expression.property(参数,propertyName);
LambdaExpression lambda=Expression.lambda(属性、参数);
string methodName=(descIndex<0)?“OrderBy”:“OrderByDescending”;
Expression methodCallExpression=Expression.Call(typeof(Queryable)、methodName、,
新类型[]{source.ElementType,property.Type},
source.Expression,Expression.Quote(lambda));
返回source.Provider.CreateQuery(methodCallExpression);
}
}
因为我在这个框架内工作,所以我不会改变这个函数的工作方式。相反,我试图用此签名重载该方法:
public static IQueryable<T> SortBy<T>(this IQueryable<T> source, string propertyName, bool nullsToEnd)
publicstaticiqueryable-SortBy(此IQueryable源代码,字符串propertyName,boolnullstoend)
我遇到的问题是,我无法弄清楚如何编辑“methodName”以专门允许这种排序(末尾为空的A-Z)发生
有什么办法可以解决这个问题吗
谢谢我认为没有一个方法名称本身可以满足您的要求。相反,在这个场景中,您需要选择一个不同的方法重载,一个采用自定义IComparer实例的方法重载。然后,您需要实现一个包装Comparer.Default的IComparer,在不涉及null时返回该比较器的结果,并在不涉及null时将null排序到末尾 请注意,如果您希望OrderBy和OrderByDescending案例的结尾都为null,则需要相应地调整IComparer实现。要么让它同时处理空值和升序/降序选项,要么让它在执行“降序”情况时将空值排序到开头(就个人而言,由于您必须根据升序/降序状态调整IComparer,因此我会继续让IComparer处理升序/降序部分) 例如:
class NullsAtEndComparer<T> : IComparer<T> where T : class
{
private static readonly IComparer<T> _baseComparer = Comparer<T>.Default;
private readonly bool _ascending;
public NullsAtEndComparer(bool ascending = true)
{
_ascending = ascending;
}
public int Compare(T t1, T t2)
{
if (object.ReferenceEquals(t1, t2))
{
return 0;
}
if (t1 == null)
{
return 1;
}
if (t2 == null)
{
return -1;
}
return _ascending ? _baseComparer.Compare(t1, t2) : _baseComparer.Compare(t2, t1);
}
}
class NullsAtEndComparer:IComparer其中T:class
{
私有静态只读IComparer _baseComparer=Comparer.Default;
私有只读布尔值;
公共NullsAtEndComparer(布尔升序=真)
{
_上升=上升;
}
公共整数比较(t1,t2)
{
if(object.ReferenceEquals(t1,t2))
{
返回0;
}
如果(t1==null)
{
返回1;
}
如果(t2==null)
{
返回-1;
}
返回_升序?_baseComparer.Compare(t1,t2):_baseComparer.Compare(t2,t1);
}
}
然后对于“结尾处为空”的场景,只需始终使用OrderBy方法并为该方法提供上述IComparer实现的实例。请注意我的编辑,其中我修复了排序错误。比较器需要确保所有相同的输入对都被认为是相等的,即使它们都为null。使用object.ReferenceEquals()可以实现这一点,并且在将同一对象作为两个操作数传递时,还提供了快捷方式优化。