commits列表 30 项
提交内容 4/4
orderby,注意字段是小写的,支持多个排序,比如id,name desc
framework/PasteApeart.Application/PasteApeart.Application.xml
diff --git a/framework/PasteApeart.Application/PasteApeart.Application.xml b/framework/PasteApeart.Application/PasteApeart.Application.xml
index dc54162..0aeaeec 100644
--- a/framework/PasteApeart.Application/PasteApeart.Application.xml
+++ b/framework/PasteApeart.Application/PasteApeart.Application.xml
@@ -1199,6 +1199,15 @@
             <returns></returns>
             <exception cref="T:PasteApeart.Application.Contracts.PasteCodeException"></exception>
         </member>
+        <member name="M:PasteApeart.Application.PasteDefaultHelper.PasteOrder(System.Linq.IQueryable,System.String)">
+            <summary>
+            支持多排序 比如id,name desc等
+            </summary>
+            <param name="query"></param>
+            <param name="ordering"></param>
+            <returns></returns>
+            <exception cref="T:System.ArgumentException"></exception>
+        </member>
         <member name="M:PasteApeart.Application.PasteDefaultHelper.ReadCurrentPropertyThrowException(System.Type,System.String)">
             <summary>
             查找字段 应对new的情况
framework/PasteApeart.Application/PasteDefaultHelper.cs
diff --git a/framework/PasteApeart.Application/PasteDefaultHelper.cs b/framework/PasteApeart.Application/PasteDefaultHelper.cs
index 588293f..736db2f 100644
--- a/framework/PasteApeart.Application/PasteDefaultHelper.cs
+++ b/framework/PasteApeart.Application/PasteDefaultHelper.cs
@@ -2020,29 +2020,32 @@ namespace PasteApeart.Application
             var actionOrderby = false;
             if (!String.IsNullOrEmpty(orderby))
             {
-                //这里做查找和适配
-                var fieldName = orderby.Split(" ")[0];
-                var findOrderProperty = ReadCurrentProperty(entityType, fieldName);
-                if (findOrderProperty != null)
-                {
-                    var orderType = "OrderByDescending";
-                    if (!orderby.Contains(" desc", StringComparison.OrdinalIgnoreCase))
-                    {
-                        orderType = "OrderBy";
-                    }
-                    // 构建排序表达式 默认 OrderByDescending(x=>x.Id)
-                    var parameter = Expression.Parameter(entityType, "x");
-                    var propertyAccess = Expression.Property(parameter, findOrderProperty);
-                    var lambda = Expression.Lambda(propertyAccess, parameter);
-                    // 使用正确的属性类型作为排序键类型
-                    var orderByDescendingCall = Expression.Call(
-                        typeof(Queryable), orderType,
-                        new Type[] { entityType, findOrderProperty.PropertyType }, // 使用实际的属性类型
-                        query.Expression,
-                        lambda);
-                    query = query.Provider.CreateQuery(orderByDescendingCall);
-                    actionOrderby = true;
-                }
+                #region 下面是旧版本,只支持单个排序
+                //var fieldName = orderby.Split(" ")[0];
+                //var findOrderProperty = ReadCurrentProperty(entityType, fieldName);
+                //if (findOrderProperty != null)
+                //{
+                //    var orderType = "OrderByDescending";
+                //    if (!orderby.Contains(" desc", StringComparison.OrdinalIgnoreCase))
+                //    {
+                //        orderType = "OrderBy";
+                //    }
+                //    // 构建排序表达式 默认 OrderByDescending(x=>x.Id)
+                //    var parameter = Expression.Parameter(entityType, "x");
+                //    var propertyAccess = Expression.Property(parameter, findOrderProperty);
+                //    var lambda = Expression.Lambda(propertyAccess, parameter);
+                //    // 使用正确的属性类型作为排序键类型
+                //    var orderByDescendingCall = Expression.Call(
+                //        typeof(Queryable), orderType,
+                //        new Type[] { entityType, findOrderProperty.PropertyType }, // 使用实际的属性类型
+                //        query.Expression,
+                //        lambda);
+                //    query = query.Provider.CreateQuery(orderByDescendingCall);
+                //    actionOrderby = true;
+                //}
+                #endregion
+                //支持多个查询,比如id,name desc
+                query = PasteOrder(query, orderby);
             }
             if (!actionOrderby)
             {
@@ -2065,6 +2068,75 @@ namespace PasteApeart.Application
         }
 
         /// <summary>
+        /// 支持多排序 比如id,name desc等
+        /// </summary>
+        /// <param name="query"></param>
+        /// <param name="ordering"></param>
+        /// <returns></returns>
+        /// <exception cref="ArgumentException"></exception>
+        private IOrderedQueryable PasteOrder(IQueryable query, string ordering)
+        {
+            //if (string.IsNullOrWhiteSpace(ordering))
+            //return query.OrderBy(x => 1);
+            if (String.IsNullOrEmpty(ordering))
+            {
+                return (IOrderedQueryable)query;
+            }
+            // 分割多个排序字段
+            var orderClauses = ordering.Split(',', StringSplitOptions.RemoveEmptyEntries);
+            IOrderedQueryable orderedQuery = null;
+            var eType = query.ElementType;
+            foreach (var clause in orderClauses)
+            {
+                var parts = clause.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries);
+                if (parts.Length == 0) continue;
+
+                var fieldName = parts[0];
+                var descending = false;
+                if (parts.Length > 1)
+                {
+                    descending = parts.Length > 1 &&
+                                   (parts[1].Equals("desc", StringComparison.OrdinalIgnoreCase) ||
+                                    parts[1].Equals("descending", StringComparison.OrdinalIgnoreCase));
+                }
+                var propertyInfo = ReadTypeProperties(eType).FirstOrDefault(x => string.Equals(x.Name, fieldName, StringComparison.OrdinalIgnoreCase));
+                if (propertyInfo == null)
+                {
+                    throw new ArgumentException($"类型 '{eType.Name}' 中不存在属性 '{fieldName}'");
+                }
+
+                // 构建表达式
+                var parameter = Expression.Parameter(eType, "x");
+                var property = Expression.Property(parameter, propertyInfo);
+                var lambda = Expression.Lambda(property, parameter);
+
+                if (orderedQuery == null)
+                {
+                    // 第一个排序字段
+                    var methodName = descending ? "OrderByDescending" : "OrderBy";
+                    var methodCall = Expression.Call(
+                        typeof(Queryable), methodName,
+                        new Type[] { eType, property.Type },
+                        query.Expression, Expression.Quote(lambda));
+
+                    orderedQuery = (IOrderedQueryable)query.Provider.CreateQuery(methodCall);
+                }
+                else
+                {
+                    // 后续排序字段
+                    var methodName = descending ? "ThenByDescending" : "ThenBy";
+                    var methodCall = Expression.Call(
+                        typeof(Queryable), methodName,
+                        new Type[] { eType, property.Type },
+                        orderedQuery.Expression, Expression.Quote(lambda));
+
+                    orderedQuery = (IOrderedQueryable)orderedQuery.Provider.CreateQuery(methodCall);
+                }
+            }
+            return orderedQuery ?? (IOrderedQueryable)query;
+        }
+
+        /// <summary>
         /// 查找字段 应对new的情况
         /// </summary>
         /// <param name="entityType"></param>
framework/PasteApeart.Helper/PasteApeartAttribute.cs
diff --git a/framework/PasteApeart.Helper/PasteApeartAttribute.cs b/framework/PasteApeart.Helper/PasteApeartAttribute.cs
index a257709..cb9d5f6 100644
--- a/framework/PasteApeart.Helper/PasteApeartAttribute.cs
+++ b/framework/PasteApeart.Helper/PasteApeartAttribute.cs
@@ -2025,10 +2025,10 @@ namespace PasteApeart.Helper
     {
 
         /// <summary>
-        /// 排序
+        /// 排序 不写表示当前字段的默认值,小写开头(ui要判断样式) 比如nickName和nickName desc
         /// </summary>
-        /// <param name="acsName">升序 示例:Id,不写默认为当前字段升序</param>
-        /// <param name="descName">降序 示例:Id desc,不写为当前字段降序</param>
+        /// <param name="acsName">升序 示例:nickName,不写默认为当前字段升序</param>
+        /// <param name="descName">降序 示例:nickName desc,不写为当前字段降序</param>
         public PasteOrderbyAttribute(string acsName = null, string descName = null)
         {
             base.Name = "orderby";
framework/PasteApeart.Helper/QueryableExtensions.cs
diff --git a/framework/PasteApeart.Helper/QueryableExtensions.cs b/framework/PasteApeart.Helper/QueryableExtensions.cs
index 0294c71..166227b 100644
--- a/framework/PasteApeart.Helper/QueryableExtensions.cs
+++ b/framework/PasteApeart.Helper/QueryableExtensions.cs
@@ -1,4 +1,4 @@
-using System.Linq.Expressions;
+using System.Linq.Expressions;
 using System.Reflection;
 
 namespace PasteApeart.Helper
@@ -42,16 +42,16 @@ namespace PasteApeart.Helper
                 //var property = Expression.Property(parameter, fieldName);
                 //var lambda = Expression.Lambda(property, parameter);
                 // 使用 GetProperty 而不是 Expression.Property
-                var propertyInfo = eType.GetProperty(fieldName,
-                    BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.IgnoreCase);
-
-                if (propertyInfo == null)
-                {
-                    // 如果当前类型没有,查找基类的属性
-                    propertyInfo = eType.GetProperty(fieldName,
-                        BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
-                }
-
+                //var propertyInfo = eType.GetProperty(fieldName,
+                //    BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.IgnoreCase);
+
+                //if (propertyInfo == null)
+                //{
+                //    // 如果当前类型没有,查找基类的属性
+                //    propertyInfo = eType.GetProperty(fieldName,
+                //        BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
+                //}
+                var propertyInfo = ReadTypeProperties(eType).FirstOrDefault(x => string.Equals(x.Name, fieldName, StringComparison.OrdinalIgnoreCase));
                 if (propertyInfo == null)
                 {
                     throw new ArgumentException($"类型 '{eType.Name}' 中不存在属性 '{fieldName}'");
@@ -129,15 +129,15 @@ namespace PasteApeart.Helper
                 //var lambda = Expression.Lambda(property, parameter);
 
                 // 使用 GetProperty 而不是 Expression.Property
-                var propertyInfo = eType.GetProperty(fieldName,
-                    BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.IgnoreCase);
-
-                if (propertyInfo == null)
-                {
-                    // 如果当前类型没有,查找基类的属性
-                    propertyInfo = eType.GetProperty(fieldName,
-                        BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
-                }
+                //var propertyInfo = eType.GetProperty(fieldName,
+                //    BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.IgnoreCase);
+                var propertyInfo = ReadTypeProperties(eType).FirstOrDefault(x => string.Equals(x.Name, fieldName, StringComparison.OrdinalIgnoreCase));
+                //if (propertyInfo == null)
+                //{
+                //    // 如果当前类型没有,查找基类的属性
+                //    propertyInfo = eType.GetProperty(fieldName,
+                //        BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
+                //}
 
                 if (propertyInfo == null)
                 {
@@ -175,5 +175,51 @@ namespace PasteApeart.Helper
 
             return orderedQuery ?? (IOrderedQueryable)query;
         }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="searchType"></param>
+        /// <returns></returns>
+        private static PropertyInfo[] ReadTypeProperties(Type searchType)
+        {
+
+            var typeName = searchType.FullName;
+            // 使用GetOrCreate替代TryGetValue+Set
+            //return t.GetProperties(); // 耗时的反射操作
+            var allProperties = searchType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
+
+            // 如果有属性被隐藏(new),才需要复杂处理
+            var hasDuplicates = allProperties.Length != allProperties.Select(p => p.Name).Distinct().Count();
+            if (!hasDuplicates)
+            {
+                // 没有重复属性名,直接返回
+                return allProperties;
+            }
+            // 有重复属性名,进行分组处理
+            var propertyGroups = allProperties.GroupBy(p => p.Name);
+            var result = new PropertyInfo[propertyGroups.Count()];
+
+            int index = 0;
+            foreach (var group in propertyGroups)
+            {
+                // 手动查找,避免 LINQ 的开销
+                PropertyInfo selected = null;
+                foreach (var prop in group)
+                {
+                    if (prop.DeclaringType == searchType)
+                    {
+                        selected = prop;
+                        break;  // 找到当前类声明的,立即退出
+                    }
+                    selected ??= prop;  // 否则保留第一个
+                }
+                result[index++] = selected!;
+            }
+
+            return result;
+
+
+        }
     }
 }
​ ​