第7章 分页之模型分页(物理分页)

news2024/11/19 6:12:43

    模型分页主要通过前端页面中的分页控件,向后端指定路由(控制器行为方法),传递相等的参数,然后间接的通过后端程序从数据库指定表中获取一些指定行的数据,然后把这些数据在前端页面渲染显示出来。模型分页的主要用于前端页面与后端程序之间的直接的数据交互操作,并且模型分页的实例数据最终需要在前端页面上进渲染显示的,因此又称模型分页为:物理分页,与之相对应的是:逻辑分页,这将在下面的章节中进行讲解。

    不管理是“物理分页”还是“逻辑分页”,二者都是,只把当前页面渲染显示所必须的数据,通过当前程序间接的从数据库的指定表中取出并存储到内存中,这种操作的好处是尽量减少资源开锁,特别是内存的开销。

1 准备工作

1.1 Data.Extensions.ParameterRebinder

using System.Linq.Expressions;

namespace Data.Extensions

{

    /// <summary>

    /// 【参数重新绑定--类】

    /// <remarks>

    /// 摘要:

    ///     通过该类中的方法成员把1个指定的“lambda”表达式,中的指定参数替换(这里主要指“lambda”表达式中指针实例的替换)后,返回1个新的被替换后的“lambda”表达式。

    /// </remarks>

    /// </summary>

    public class ParameterRebinder : ExpressionVisitor

    {

        #region 拷贝构造方法与变量

        /// <summary>

        /// 【映射】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定的典实例,该实例中存储着“lambda”表达式替换的需要的参数实例。

        /// </remarks>

        /// </summary>

        private readonly Dictionary<ParameterExpression, ParameterExpression> map;

        ///<param name="map">字典实例,该实例中存储着“lambda”表达式替换的需要的参数实例。</param>

        /// <summary>

        /// 【拷贝构建方法】

        /// <remarks>

        /// 摘要:

        ///     通过拷贝构建方法,实例化该类中的字典成员变量。

        /// </remarks>

        /// </summary>

        public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)

        {

            this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();

        }

        #endregion

        #region 方法--私有/保护--覆写

        ///<param name="p">1个指定“lambda”表达式的指针实例。</param>

        /// <summary>

        /// 【参数访问】

        /// <remarks>

        /// 摘要:

        ///     通过该方法将调用其基类同名方法,把1个指定的“lambda”表达式,中的指定参数替换后,返回1个新的被替换后的“lambda”表达式。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     1个新的被替换后的“lambda”表达式。

        /// </returns>

        /// </summary>

        protected override Expression VisitParameter(ParameterExpression p)

        {

            ParameterExpression replacement;

            //如果字典实例包含指针实例,则抛出指针实例,并使用抛出指针实例替换原“lambda”表达式中的指针实例。

            if (map.TryGetValue(p, out replacement!)) p = replacement;

            //调用其基类同名方法,获取1个新的被替换后的“lambda”表达式。

            return base.VisitParameter(p);

        }

        #endregion

        #region 方法

        ///<param name="map">字典实例,该实例中存储着“lambda”表达式替换的需要的参数实例。</param>

        ///<param name="exp">1个将被替换参数的“lambda”表达式。</param>

        /// <summary>

        /// 【参数替换】

        /// <remarks>

        /// 摘要:

        ///     通过该方法把1个指定的“lambda”表达式,中的指定参数替换后,返回1个新的被替换后的“lambda”表达式。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     1个新的被替换后的“lambda”表达式。

        /// </returns>

        /// </summary>

        public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)

        {

            return new ParameterRebinder(map).Visit(exp);

        }

        #endregion

    }

}

1.2 Data.Extensions.ExpressionExtension

using System.Linq.Expressions;

namespace Data.Extensions

{

    /// <summary>

    /// “lambda”表达式扩展--类】

    /// <remarks>

    /// 摘要:

    ///     通过该类中的方法成员获取1个指定实例的“lambda”表达式实例,或组合出该指定实例的1个新的“lambda”表达式实例。

    /// </remarks>

    /// </summary>

    public static class ExpressionExtension

    {

        ///<typeparam name="T">泛型类型实例(1个指定类的类型实例)</typeparam>

        /// <summary>

        /// 【真】

        /// <remarks>

        /// 摘要:

        ///     该方法以泛型形式获取1个指定实例的非空“lambda”表达式实例。

        /// 说明:

        ///     1、这种方式是以泛型形式获取1个指定实例的非空“lambda”表达式实例的最简实现。

        ///     21个指定实例以这种方式执行“lambda”操作后,该实例中包含的所有子实例都为:true,即不执行筛选过滤操作。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     1个指定实例的非空“lambda”表达式实例。

        /// </returns>

        /// </summary>

        public static Expression<Func<T, bool>> True<T>()

        {

            return f => true;

        }

        ///<typeparam name="T">泛型类型实例(1个指定类的类型实例)</typeparam>

        /// <summary>

        /// 【假】

        /// <remarks>

        /// 摘要:

        ///     该方法以泛型形式获取1个指定实例的非空“lambda”表达式实例。

        /// 说明:

        ///     1、这种方式是以泛型形式获取1个指定实例的非空“lambda”表达式实例的最简实现。

        ///     21个指定实例以这种方式执行“lambda”操作后,该实例中所包含的所有子实例都为:false,即该实例中不包含的任何的子实例,或者说子实例都被筛选过滤掉了。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     1个指定实例的非空“lambda”表达式实例。

        /// </returns>

        /// </summary>

        public static Expression<Func<T, bool>> False<T>()

        {

            return f => false;

        }

        ///<typeparam name="T">泛型类型实例(1个指定类的类型实例)</typeparam>

        ///<param name="first">1“lambda”表达式实例。</param>

        ///<param name="second">2“lambda”表达式实例。</param>

        ///<param name="merge">1个将被替换参数的“lambda”表达式。</param>

        /// <summary>

        /// 【组合】

        /// <remarks>

        /// 摘要:

        ///     该方法是以泛型形式把第1“lambda”表达式指针与第1“lambda”表达式中的主体和第2“lambda”表达式中的主体,共同组合出完整的新的“lambda”表达式。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     1个同组合出完整的新的“lambda”表达式。

        /// </returns>

        /// </summary>

        public static Expression<T> Compose<T>(this Expression<T> first,

            Expression<T> second,

            Func<Expression, Expression, Expression> merge)

        {

            //获取把第2“lambda”表达式指针及其指针实例,并存储到到字典实例中。

            var map = first.Parameters//1“lambda”表达式指针

                .Select((f, i) => new { f, s = second.Parameters[i] })//second.Parameters[i]:2“lambda”表达式指针。第1“lambda”表达式指针被第2“lambda”表达式指针所替换。

                .ToDictionary(p => p.s, p => p.f);//把第2“lambda”表达式指针及其指针实例,存储到字典实例中。

            //通过典实例中的数据,对第2“lambda”表达式中的主体中的指针替换后,获取1个新的第2“lambda”表达式中的主体

            var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);

            // 把第1“lambda”表达式指针与第1“lambda”表达式中的主体和第2“lambda”表达式中的主体,共同组合出完整的新的“lambda”表达式。

            return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);

        }

        ///<typeparam name="T">泛型类型实例(1个指定类的类型实例)</typeparam>

        ///<param name="first">1“lambda”表达式实例。</param>

        ///<param name="second">2“lambda”表达式实例。</param>

        /// <summary>

        /// 【逻辑与操作】

        /// <remarks>

        /// 摘要:

        ///     该方法是以泛型形式把第1“lambda”表达式指针与第1“lambda”表达式中的主体和第2“lambda”表达式中的主体,以逻辑与操作方式,共同组合出完整的新的“lambda”表达式。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     以逻辑与操作方式,共同组合出完整的新的“lambda”表达式。

        /// </returns>

        /// </summary>

        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first,

            Expression<Func<T, bool>> second)

        {

            return first.Compose(second, Expression.And);

        }

        ///<typeparam name="T">泛型类型实例(1个指定类的类型实例)</typeparam>

        ///<param name="first">1“lambda”表达式实例。</param>

        ///<param name="second">2“lambda”表达式实例。</param>

        /// <summary>

        /// 【逻辑或操作】

        /// <remarks>

        /// 摘要:

        ///    该方法是以泛型形式把第1“lambda”表达式指针与第1“lambda”表达式中的主体和第2“lambda”表达式中的主体,以逻辑或操作方式,共同组合出完整的新的“lambda”表达式。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     以逻辑或操作方式,共同组合出完整的新的“lambda”表达式。

        /// </returns>

        /// </summary>

        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first,

            Expression<Func<T, bool>> second)

        {

            return first.Compose(second, Expression.Or);

        }

    }

}

1.3 Data.Extensions.QueryableExtension

using System.Linq.Expressions;

namespace Data.Extensions

{

    /// <summary>

    /// Queryable扩展类--类】

    /// <remarks>

    /// 摘要:

    ///    “IQueryable”实例操作方法通过该类中相应方法成员进行了扩展,以提升 “IQueryable”实例操作方法的功能,

    /// 这些被扩展的方法包括:LongSkip OrderByOrderByDescending

    /// </remarks>

    /// </summary>

    public static class QueryableExtension

    {

        ///<typeparam name="TSource">泛型类型实例(1个指定类的类型实例)</typeparam>

        ///<param name="source">以枚举数接口实例进行存储的1个指定类型的数据源(枚举数接口实例=长串型,包含:数组、列表、字典等)</param>

        ///<param name="LongCount">需要跳过项的总计值。</param>

        /// <summary>

        /// 【长整型跳过】

        /// <remarks>

        /// 摘要:

        ///    由于“System.Linq.Queryable.Skip”方法只支持类型为“int”“Int32”类型的需要跳过项的总计值,为了支持类型为“long”“Int64”的需要跳过项的总计值,从而定义了该扩展方法。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    “IQueryable”实例,该实例存储着1个指定类型的数据源(枚举数接口实例=长串型,包含:数组、列表、字典等)在执行过跳过项操作后所剩余的数据源。

        /// </returns>

        /// </summary>

        public static IQueryable<TSource> LongSkip<TSource>(this IQueryable<TSource> source, long LongCount)

        {

            //“Math.DivRem()”方法在 C#中的用于除法和计算两个数的商:“quotients”(取整操作,“quotients”必须被定义为“long”“Int64”类型,因为“quotients”的最大值远远大于“int.MaxValue”)

            //并在输出参数中返回余数:“remainder”(取余,“remainder”可以转换为“int”“Int32”类型,因为“remainder”的最大值一定小于“int.MaxValue”)

            long quotients = Math.DivRem(LongCount, int.MaxValue, out long remainder);

            //先执行从数据源中跳过quotients*int.MaxValue项操作。

            for (long i = 0; i < quotients; i += 1)

                source = source.Skip(int.MaxValue);

            //如果余数(“remainder”)不为:0,则在上一个操作的基础上,再执行跳过remainder项操作。

            if (remainder != 0)

                source = source.Skip((int)remainder);

            return source;

        }

        ///<typeparam name="TSource">泛型类型实例(1个指定类的类型实例)</typeparam>

        ///<param name="source">以枚举数接口实例进行存储的1个指定类型的数据源(枚举数接口实例=长串型,包含:数组、列表、字典等)</param>

        ///<param name="propertyName">定类的指定属性成员名(或对应表中的相应字段名)</param>

        /// <summary>

        /// 【正序排序】

        /// <remarks>

        /// 摘要:

        ///    “System.Linq.Queryable.OrderBy”方法进行扩展,使用支持以指定类的指定属性成员名(或对应表中的相应字段名)字符串进行正序排序操作。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     “IQueryable”实例,该实例存储着1个指定类型的数据源(枚举数接口实例=长串型,包含:数组、列表、字典等)在执行过正序排序操作后的数据源。

        /// </returns>

        /// </summary>

        public static IOrderedQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string propertyName)

        {

            //如果用于排序操作的参数实例(指定类的指定属性成员名(或对应表中的相应字段名)为空 ,则直接返回原数据源。

            if (string.IsNullOrEmpty(propertyName))

            {

                return (IOrderedQueryable<TSource>)source;

            }

            //为指定类的排序操作构建相应的“lambda”表达式。

            //“lambda”表达式的指针

            var param = Expression.Parameter(typeof(TSource), "p");

            //“lambda”表达式的指针与指定类的指定属性成员(或对应表中的相应字段)实例的组合。

            var property = Expression.Property(param, propertyName);

            为指定类组合出完整的“lambda”表达式。

            var exp = Expression.Lambda(property, param);

            //委托方法参数实例,通过委托方法参数实例,生成一个指定的正序排序“lambda”表达式。

            MethodCallExpression resultExpression = Expression.Call(typeof(Queryable), "OrderBy", new Type[] { source.ElementType, exp.Body.Type }, source.Expression, exp);

            //返回经过正序排序后的数据源。

            return (IOrderedQueryable<TSource>)source.Provider.CreateQuery<TSource>(resultExpression);

        }

        ///<typeparam name="TSource">泛型类型实例(1个指定类的类型实例)</typeparam>

        ///<param name="source">以枚举数接口实例进行存储的1个指定类型的数据源(枚举数接口实例=长串型,包含:数组、列表、字典等)</param>

        ///<param name="propertyName">定类的指定属性成员名(或对应表中的相应字段名)</param>

        /// <summary>

        /// 【倒序排序】

        /// <remarks>

        /// 摘要:

        ///    “System.Linq.Queryable.OrderByDescending”方法进行扩展,使用支持以指定类的指定属性成员名(或对应表中的相应字段名)字符串进行倒序排序操作。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///      “IQueryable”实例,该实例存储着1个指定类型的数据源(枚举数接口实例=长串型,包含:数组、列表、字典等)在执行过倒序排序操作后的数据源。

        /// </returns>

        /// </summary>

        public static IOrderedQueryable<TSource> OrderByDescending<TSource>(this IQueryable<TSource> source, string propertyName)

        {

            //如果用于排序操作的参数实例(指定类的指定属性成员名(或对应表中的相应字段名)为空 ,则直接返回原数据源。

            if (string.IsNullOrEmpty(propertyName))

            {

                return (IOrderedQueryable<TSource>)source;

            }

            //为指定类的排序操作构建相应的“lambda”表达式。

            //“lambda”表达式的指针

            var param = Expression.Parameter(typeof(TSource), "p");

            //“lambda”表达式的指针与指定类的指定属性成员(或对应表中的相应字段)实例的组合。

            var property = Expression.Property(param, propertyName);

            为指定类组合出完整的“lambda”表达式。

            var exp = Expression.Lambda(property, param);

            //委托方法参数实例,通过委托方法参数实例,生成一个指定的倒序排序“lambda”表达式。

            MethodCallExpression resultExpression = Expression.Call(typeof(Queryable), "OrderByDescending", new Type[] { source.ElementType, exp.Body.Type }, source.Expression, exp);

            //返回经过倒序排序后的数据源。

            return (IOrderedQueryable<TSource>)source.Provider.CreateQuery<TSource>(resultExpression);

        }

    }

}

1.4 Data.Extensions.EnumerableExtension

namespace Data.Extensions

{

    /// <summary>

    /// 【可枚举扩展类--类】

    /// <remarks>

    /// 摘要:

    ///    “IEnumerable”(可枚)实例操作方法通过该类中相应方法成员进行了扩展,以提升 “IEnumerable”实例操作方法的功能,

    /// 这些被扩展的方法包括:LongSkip

    /// </remarks>

    /// </summary>

    public static class EnumerableExtension

    {

        ///<typeparam name="TSource">泛型类型实例(1个指定类的类型实例)</typeparam>

        ///<param name="source">以枚举数接口实例进行存储的1个指定类型的数据源(枚举数接口实例=长串型,包含:数组、列表、字典等)</param>

        ///<param name="LongCount">需要跳过项的总计值。</param>

        /// <summary>

        /// 【长整型跳过】

        /// <remarks>

        /// 摘要:

        ///    由于“System.Linq.Enumerable.Skip”方法只支持类型为“int”“Int32”类型的需要跳过项的总计值,为了支持类型为“long”“Int64”的需要跳过项的总计值,从而定义了该扩展方法。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    “IEnumerable”(可枚)实例,该实例存储着1个指定类型的数据源(枚举数接口实例=长串型,包含:数组、列表、字典等)在执行过跳过项操作后所剩余的数据源。

        /// </returns>

        /// </summary>

        public static IEnumerable<TSource> LongSkip<TSource>(this IEnumerable<TSource> source, long LongCount)

        {

            //“Math.DivRem()”方法在 C#中的用于除法和计算两个数的商:“quotients”(取整操作,“quotients”必须被定义为“long”“Int64”类型,因为“quotients”的最大值远远大于“int.MaxValue”)

            //并在输出参数中返回余数:“remainder”(取余,“remainder”可以转换为“int”“Int32”类型,因为“remainder”的最大值一定小于“int.MaxValue”)

            long quotients = Math.DivRem(LongCount, int.MaxValue, out long remainder);

            //先执行从数据源中跳过quotients*int.MaxValue项操作。

            for (long i = 0; i < quotients; i += 1)

                source = source.Skip(int.MaxValue);

            //如果余数(“remainder”)不为:0,则在上一个操作的基础上,再执行跳过remainder项操作。

            if (remainder != 0)

                source = source.Skip((int)remainder);

            return source;

        }

    }

}

2 物理分页(模型分页)

2.1 WebApi.Models.PageModel<T>

namespace WebApi.Models

{

    ///<typeparam name="T">泛型类型实例(1个指定类的类型实例)</typeparam>

    /// <summary>

    /// 【页模型--纪录】

    /// </summary>

    /// <remarks>

    /// 摘要:

    ///     通过该纪录的属性成员对1指定逻辑(内存)页面内的指定实体/模型的所有实例进行存储,这些实例数据为页面的渲染显示提供数据支撑。

    ///  说明:

    ///     该模型纪录的实例实质上也是逻辑(内存)页面,但是该实例直接为页面的渲染显示提供数据支撑,所以把该模型类的实例称之为:物理页。

    /// </remarks>

    public record PageModel<T>

    {

        /// <summary>

        /// 【当前页】

        /// <remarks>

        /// 摘要:

        ///     获取/设置当前页,即从前端页面所传递过来的当前页面的长整型索引值,默认值:1,即当前前端页面所渲染显示的是第1页。

        /// </remarks>

        /// </summary>

        public long PageIndex { get; set; } = 1;

        /// <summary>

        /// 【页面大小】

        /// <remarks>

        /// 摘要:

        ///     获取/设置页面大小,即前端页面内最多所渲染显示的实例项的长型个数值,默认值:10,即页面内最多渲染显示10项实例。

        /// </remarks>

        /// </summary>

        public int PageSize { set; get; } = 10;

        /// <summary>

        /// 【总计值】

        /// <remarks>

        /// 摘要:

        ///     获取/设置符合指定条件的实例项的长整型总计值,即前端页面中所有页面所渲染显示的实例项的长型个数值,默认值:0,即还没有任何的实例数据需要前端页面进行渲染显示。

        /// </remarks>

        /// </summary>

        public long TotalCount { get; set; } = 0;

        /// <summary>

        /// 【总页数】

        /// <remarks>

        /// 摘要:

        ///     获取/设置当前页,即从指定表中获取当前逻辑页面内的所有实例,可以分为页数的总计值。

        /// 说明:

        ///     “Math.Ceiling”方法:向上进位取整,即如果除不尽,那么就向上进1,例如:Math.Ceiling(2.1) = 3;与之相对应的是Math.Floor方法:向下舍位取整。例:Math.Floor(2.9)=2

        /// </remarks>

        /// </summary>

        public long TotalPage => (long)Math.Ceiling((decimal)TotalCount / PageSize);

        /// <summary>

        /// 【数据】

        /// <remarks>

        /// 摘要:

        ///     获取/设置可枚举实例,把1指定逻辑页面内的指定实体/模型的所有实例存储到该可枚举实例中,从而为前端当页面的渲染显示提供数据支撑。

        /// </remarks>

        /// </summary>

        public IEnumerable<T> Data { get; set; }

    }

}

2.2 WebApi.Models.MessageModel<T>

namespace WebApi.Models

{

    ///<typeparam name="T">泛型类型实例(1个指定类的类型实例)</typeparam>

    /// <summary>

    /// 【消息模型--纪录】

    /// </summary>

    /// <remarks>

    /// 摘要:

    ///     通过该纪录的属性成员对指定“Api”控制器行方法的执行操作结果进行存储,为客户端页面的渲染提供数据支撑。

    /// </remarks>

    public record MessageModel<T>

    {

        /// <summary>

        /// 【状态码】

        /// <remarks>

        /// 摘要:

        ///     获取/设置指定控制器行方法的执行结果状态码的整型值,默认值:200(执行成功的状态码)。

        /// </remarks>

        /// </summary>

        public int Status { get; set; } = 200;

        /// <summary>

        /// 【成功?】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个值false(默认值,执行失败)/true(执行成功),该值指示指定“Api”控制器行方法的执行操作是否处于成功状态。

        /// </remarks>

        /// </summary>

        public bool Success { get; set; } = false;

        /// <summary>

        /// 【信息】

        /// <remarks>

        /// 摘要:

        ///     获取/设置指定“Api”控制器行方法的执行状态所对应的解释性信息,默认值:"",即执行状态没有所对应的解释性信息。

        /// </remarks>

        /// </summary>

        public string Message { get; set; } = "";

        /// <summary>

        /// 【泛型应答实例】

        /// <remarks>

        /// 摘要:

        ///     获取/设置泛型实例,该实例泛型用于存储指定实体/模型类的所有实例,为客户端页面的渲染提供数据支撑。

        /// </remarks>

        /// </summary>

        public T Response { get; set; }

    }

}

2.3 WebApi.Models.PaginationModel

namespace WebApi.Models

{

    /// <summary>

    /// 【分页模型--纪录】

    /// </summary>

    /// <remarks>

    /// 摘要:

    ///     通过该纪录的属性成员对前端页面RUL路由或表单中所传递的分页参数进行存储,以实现页面对符合条件的数据进行渲染显示。

    /// </remarks>

    public record PaginationModel

    {

        /// <summary>

        /// 【当前页】

        /// <remarks>

        /// 摘要:

        ///     获取/设置当前页,即从前端页面所传递过来的当前页面的长整型索引值,默认值:1,即当前前端页面所渲染显示的是第1页。

        /// </remarks>

        /// </summary>

        public long PageIndex { get; set; } = 1;

        /// <summary>

        /// 【页面大小】

        /// <remarks>

        /// 摘要:

        ///     获取/设置页面大小,即前端页面内最多所渲染显示的实例项的长型个数值,默认值:10,即页面内最多渲染显示10项实例。

        /// </remarks>

        /// </summary>

        public int PageSize { get; set; } = 10;

        /// <summary>

        /// 【排序字段】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定实例的排序字段及其排序方式,例如:Filed="Id"&&Type="desc""{\"Filed\":\"id\",\"Type\":\"desc\"}"

        /// </remarks>

        /// </summary>

        public string OrderByFiled { get; set; }

        /// <summary>

        /// 【筛选条件集】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定实例的筛选条件,例如:Name=""&&IsActive="true""{\"Name\":\"\",\"IsActive\":true}"

        /// </remarks>

        /// </summary>

        public string QueryCondition  { get; set; }

    }

}

3 WebApi.Controllers.RoleController.GetRolePageByFromBodyAsync

   /// <summary>

        /// 【表单单击提交分页--需权限】

        /// </summary>

        /// <remarks>

        /// 摘要:

        ///     通过表单所传递的参数实例,获取符合条件的1指定页面内的所有数据,为指定页面的渲染显示提供数据支撑。

        /// 注意:

        ///     表单提交分页必须使用“[HttpPost]”进行标记。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     消息模型纪录的1个指定实例,该实例存储当前“Api”方法的执行操作结果,为客户端页面的渲染提供数据支撑。

        /// </returns>

        [HttpPost]

        public async Task<MessageModel<PageModel<Role>>> GetRolePageByFromBodyAsync([FromBody] PaginationModel pagination)

        {

            //根据筛选字符串,为角色实例组合筛选lambda”表达式实例。

            Expression<Func<Role, bool>> _expression = null;

            if (!string.IsNullOrEmpty(pagination.QueryCondition))

            {

                _expression = ExpressionExtension.True<Role>();

                Role _role = JsonConvert.DeserializeAnonymousType(pagination.QueryCondition, new Role());

                if (_role!.Id > 0)

                {

                    _expression = _expression.And(p => p.Id == _role!.Id);

                }

                if (!string.IsNullOrEmpty(_role!.Name))

                {

                    _expression = _expression.And(p => p.Name.Contains(_role!.Name));

                }

                if (pagination.QueryCondition.Contains("IsActive", StringComparison.InvariantCultureIgnoreCase))

                {

                    _expression = _expression.And(p => p.IsActive == _role!.IsActive);

                }

                if (!string.IsNullOrEmpty(_role!.Remark))

                {

                    _expression = _expression.And(p => p.Remark.Contains(_role!.Remark));

                }

            }

            IQueryable<Role> _roleQueryable = _context.GetDbSet<Role>().AsQueryable();

            //获取所有符合条件的角色实例。

            if (_expression != null)

            {

                _roleQueryable = _roleQueryable.Where(_expression);

            }

            //把所有符合条件的角色实例,按照指定字段进行排序操作。

            if (!string.IsNullOrEmpty(pagination.OrderByFiled))

            {

                var _obj = JsonConvert.DeserializeAnonymousType(pagination.OrderByFiled, new

                {

                    Filed = "",

                    Type = "",

                });

                if (_obj!.Type.Equals("asc", StringComparison.InvariantCultureIgnoreCase))

                {

                    _roleQueryable = _roleQueryable.OrderBy(_obj!.Filed);

                }

                if (_obj!.Type.Equals("desc", StringComparison.InvariantCultureIgnoreCase))

                {

                    _roleQueryable = _roleQueryable.OrderByDescending(_obj!.Filed);

                }

            }

            else

            {

                _roleQueryable = _roleQueryable.OrderBy(r => r.Id);

            }

            //根据前端页面传递的参数,从角色表中获取(1逻辑页中的)相应行数的数据,并把这些数据存储到列表实例中。

            List<Role> _roleSinglePageList = await _roleQueryable

                 .LongSkip((pagination.PageIndex - 1) * pagination.PageSize)

                 .Take(pagination.PageSize)

                 .ToListAsync();

            //实例化当前模型页(“物理页”),为当前页面的渲染显示提供数据支撑。

            PageModel<Role> _rolePageModel = new PageModel<Role>()

            {

                PageIndex = pagination.PageIndex,

                PageSize = pagination.PageSize,

                TotalCount = _roleQueryable.LongCount(),

                Data = _roleSinglePageList,

            };

            //实例化消息模型录,对当前“Api”控制器行方法的执行操作结果进行存储,为客户端页面的渲染提供数据支撑。

            MessageModel<PageModel<Role>> _roleMessageModel = new MessageModel<PageModel<Role>>()

            {

                Success = true,

                Message = "获取成功",

                Response = _rolePageModel,

            };

            return _roleMessageModel;

        }

4 调试

 对以上功能更为具体实现和注释见221228_004ShopDemo(分页之模型分页(物理分页))。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/124958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java开发 - 数据库索引的数据结构

目录 前言 题外话 什么是索引 索引的使用场景 索引的失效瞬间 索引的数据结构 Tree BTree BTree 索引提高查询效率的原因 索引的分类 innodb的特点 聚簇索引 非聚簇索引 索引操作 创建索引 查询索引 删除索引 外键 结语 前言 上一章中讲解了慢sql优化的方…

快速诊断I/O性能问题

背景客户反馈最近一段时间数据库运行缓慢&#xff0c;磁盘的压力很大&#xff0c;现在有两种不同的分析结论&#xff0c;存储设备性能下降和数据库压力变大&#xff0c;请我们进行系统的分析&#xff0c;给一个结论 现象 登录SQL专家云&#xff0c;进入性能指标页面&#xff0c…

跨境电商小白:一件代发是什么?为什么要选择Starday一件代发?

近两年经济形势比较复杂多变&#xff0c;许多人面临就业难、职场改革、行业转型等困境&#xff0c;而跨境电商行业在此形势下依靠着国家优惠政策以及中国高质量产品在海外市场获得越来越多的份额。随着跨境电商行业发展规模的扩大&#xff0c;越来越多人选择加入到跨境电商赛道…

【实时数仓】省份交易额统计接口、新老访客对比接口、访客分时统计接口

文章目录一 省份交易额统计接口1 Sugar配置&#xff08;1&#xff09;图表配置&#xff08;2&#xff09;接口地址&#xff08;3&#xff09;数据格式&#xff08;4&#xff09;执行SQL2 数据接口实现&#xff08;1&#xff09;创建地区交易额统计实体类ProvinceStats&#xff…

Kafka基础_2

Kafka系列 注&#xff1a;大家觉得博客好的话&#xff0c;别忘了点赞收藏呀&#xff0c;本人每周都会更新关于人工智能和大数据相关的内容&#xff0c;内容多为原创&#xff0c;Python Java Scala SQL 代码&#xff0c;CV NLP 推荐系统等&#xff0c;Spark Flink Kafka Hbase …

18-RocketMQ源码解读

NameServer启动 1、功能回顾 NameServer的核心作用 一是维护Broker的服务地址并进行及时的更新。 二是给Producer和Consumer提供服务获取Broker列表。 2、启动流程-源码重点 整个NameServer的核心就是一个NamesrvController对象。这个controller对象就跟java Web开发中的Contr…

3D可视化大屏是如何实现的?

3D可视化是指拥有3D效果的数据可视化&#xff0c;对于所要展示的数据可视化内容还原出真实场景&#xff0c;并实时接入数据&#xff0c;在面对复杂操作时灵活应对&#xff0c;使得整个场景在大屏上的展示更具立体、更具科技感、更具易用性。 物联网时代&#xff0c;可视化大屏的…

【发表案例】传感器网络及电路类,仅1个月26天录用

【期刊简介】IF&#xff1a;1.0-2.0&#xff0c;JCR4区&#xff0c;中科院4区 【检索情况】SCI 在检&#xff0c;正刊 【征稿领域】自主传感器网络的高级接口电路及其应用 【参考周期】2个月左右录用 【截稿日期】2023.1.31 重要时间节点&#xff1a;仅1个月26天录用 2022/12…

神经网络中常用的权重初始化方法及为何不能全初始化为0

1.权重初始化的重要性 神经网络的训练过程中的参数学习时基于梯度下降算法进行优化的。梯度下降法需要在开始训练时给每个参数赋予一个初始值。这个初始值的选取十分重要。在神经网络的训练中如果将权重全部初始化为0&#xff0c;则第一遍前向传播过程中&#xff0c;所有隐藏层…

深度学习笔记:感知机

感知机&#xff08;perceptron&#xff09;为神经网络的起源算法。感知机接受多个输入信号&#xff0c;输出一个信号。感知机信号只有0和1。 在上图的感知机中&#xff0c;x1和x2两个输入信号会分别乘以其对应权重(weight) w1和w2&#xff0c;传入神经元。神经元计算传来信号综…

Disentangled Face Attribute Editing via Instance-Aware Latent Space Search翻译

论文地址 代码地址 摘要 最近的研究表明&#xff0c;生成对抗网络&#xff08;GAN&#xff09;的潜空间中存在一组丰富的语义方向&#xff0c;这使得各种面部属性编辑应用成为可能。然而&#xff0c;现有的方法可能会遇到属性变化不好的问题&#xff0c;从而导致在更改所需属…

JS中数组对象使用

文章目录一、创建数组对象二、数组翻转1.检测数组2.翻转数组&#xff1a;三、添加数组元素1.push方法2.unshift方法四、删除数组元素1.pop方法2.shift方法&#x1f918;案例1五、数组排序六、数组索引方法1.indexof(数组元素)2.lastIndexOf方法&#x1f91f;案例2七、数组转化为…

数字验证学习笔记——SystemVerilog芯片验证16 ——约束控制块随机函数

一、约束块控制 一个类可以包含多个约束块。可以把不同约束块用于不同测试。一般情况下&#xff0c;各个约束块之间的约束内容是互相协调不违背的&#xff0c;因此通过随机函数产生随机数时可以找到合适的解 如果子类继承父类&#xff0c;也继承了父类的约束&#xff0c;这个时…

基于蒙特卡诺的电动汽车充电负荷曲线研究(充电开始时间,充电电量,充电功率)(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【C++】 STL-vector模拟实现

文章目录vector源码的内容:成员变量默认构造函数构造函数1-无参构造构造函数2 -使用n个相同的值构造构造函数3-使用迭代器区间构造拷贝构造函数**传统写法**现代写法赋值重载函数opeartor传统写法现代写法析构函数迭代器begin & end任意类型vector容器迭代器通用遍历方式:容…

paddleOCRv3之四: rec识别部分用 tensorRT(C++)部署

文章目录1. 简介&#xff1a;速度测试2. paddle 模型转onnx3. onnx转为tensorRT的engine模型4. tensorRT在vs2017中的配置5. 源码1. 简介&#xff1a; tensorRT是nvdia GPU模型部署的一个框架&#xff0c;似乎只是部分开源&#xff0c;github地址.大多数时候用这个框架去部署模…

十九、Docker容器监控之CAdvisor+InfluxDB+Granfana

1、概述 Docker自带查询容器状态的命令&#xff1a;docker stats&#xff0c;可以看到容器的ID\名称、占用CPU、内存等信息 但是我们不能时时刻刻的盯着这个命令&#xff0c;并且这个都是实时数据不能留痕&#xff0c;如果这个时候某一个容器挂了&#xff0c;我们想查看下当时…

webpack性能优化

splitChunks webpack splitChunks minSize: 只有到目标文件超过这个minSize时才会分包。cacheGroups: 可以对某个第三方包进行单独分离出来 例如&#xff1a; splitChunks: {minSize: 300 * 1024&#xff0c;chunks: all,name: aaa,cacheGroups: {jquery: {name: jquery,test…

SCADA平台在风电场测量的应用,实现风电场的高效管理

一、应用背景 随着煤碳、石油等能源的逐渐枯竭&#xff0c;人类越来越重视可再生能源的利用。风能作为一种清洁的可再生能源日益受到世界各国的重视。中国风能储量大&#xff0c;分布面广&#xff0c;仅陆地上的风能储量就约2.53亿千瓦。我国的风电发展起步较晚&#xff0c;但…

大数据教学实训沙盘介绍

沙盘的作用主要有3个&#xff1a; 1、采集真实数据&#xff0c;解决教学中缺少真实数据的困扰&#xff1b; 2、形成从数据采集、预处理、挖掘建模、模型部署的业务闭环&#xff0c;可以把构建模型发布到沙盘系统上&#xff0c;根据模型产生真实的反馈不断的修正模型精度&#x…