zoukankan      html  css  js  c++  java
  • mvc,EntityFramework调用分页存储过程

    此文讲述mvc4+entityframework6+sqlserver2008环境下调用存储过程,实现分页。

    1、分页存储过程代码如下:

    分页原理用的row_number()和over()函数实现(没有用top、not in,因为性能低;sqlserver2012有新特性,用offset、fetch实现)。

    这里支持多表查询分页。

    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    
    CREATE PROCEDURE [dbo].[Procedure_SpiltPage]
    (    
        
        @pageIndex INT =1,                     --页索引
        @pageSize INT =10,                     --页大小
        @tableName NVARCHAR(100),              --表名    
        @fieldName NVARCHAR(200) ='*',         --查询字段
        @whereCondition NVARCHAR(800) ='1=1',  --where条件
        @orderCondition NVARCHAR(200),         --order条件
        @recordTotal INT OUTPUT,               --输出记录总数
        @pageCount INT OUTPUT                  --输出分页数
    )
    
    AS
    BEGIN
        DECLARE @sqlStr NVARCHAR(1000);
        
        SET NOCOUNT ON; --不返回计数
        
        --返回记录总数
        SET @sqlStr = 'SELECT @recordTotal = COUNT(*) FROM '+@tableName+' WHERE '+@whereCondition
        EXEC sp_executesql @sqlStr,N'@recordTotal INT OUTPUT',@recordTotal OUTPUT
        SET @pageCount=(@recordTotal+@pageSize-1)/@pageSize
        
        --查询列表    
        --如果是第一页
        IF (@pageIndex<=1)
            BEGIN
                --N'表示强制转换为Unicode字符,不会乱码
                SET @sqlStr=N'SELECT TOP '+CAST(@pageSize AS VARCHAR)+' '+@fieldName+' FROM '+@tableName+' WHERE '+@whereCondition+' ORDER BY '+@orderCondition
            END
        ELSE
            BEGIN
                --为了适应多表查询,下面把第一处@fieldName改为*,这里不查询全部字段,因为第二个@fieldName
                SET @sqlStr=N'SELECT * FROM (SELECT ROW_NUMBER() OVER(ORDER BY '+@orderCondition+') AS rownum, '
                              +@fieldName+' FROM '+@tableName+' WHERE '+@whereCondition+') AS myTable WHERE rownum BETWEEN '
                              +CAST(((@pageIndex-1)*@pageSize+1) AS NVARCHAR)+' AND '+CAST((@pageIndex*@pageSize) AS NVARCHAR)
            END    
            
        EXEC (@sqlStr)
            
        SET NOCOUNT OFF;
    END
    
    GO
    存储过程

     在数据库中测试,可以如下:

    declare @total int
    declare @pageCount int
    exec Procedure_SpiltPage 1,15,'NewsInfo','*','1=1','PostTime desc',@total output,@pageCount output
    select @total as total,@pageCount as pageCounts
    执行测试代码

    2、分页实现代码:

     2.1、分页信息类如下:

    namespace WebUI.PageinationService
    {
        /// <summary>
        /// 分页信息类
        /// </summary>
        public class PageinationInfo
        {
            /// <summary>
            /// 页索引
            /// </summary>            
            public int PageIndex { get; set; }
            /// <summary>
            /// 页大小
            /// </summary>
            public int PageSize { get; set; }
            /// <summary>
            /// 总数
            /// </summary>
            public int TotalCount { get; set; }
            /// <summary>
            /// 总页数
            /// </summary>
            public int TotalPages { get; set; }
            /// <summary>
            /// 表名
            /// </summary>
            public string TableName { get; set; }
            /// <summary>
            /// 主键
            /// </summary>
            public string KeyName { get; set; }
            /// <summary>
            /// 查询字段
            /// </summary>
            public string FieldName { get; set; }
            /// <summary>
            /// where条件(不带'where')
            /// </summary>
            public string WhereCondition { get; set; }
            /// <summary>
            /// 排序条件,如:id desc ,或者:id desc,name asc
            /// </summary>
            public string OrderCondition { get; set; }
        }
    }
    分页信息类

     2.2、分页数据类(用以返回)

    namespace WebUI.PageinationService
    {
        /// <summary>
        /// 分页数据类
        /// 用以将分页集合和总数,总页数等打包一起返回
        /// </summary>
        public class PageinationData
        {
            /// <summary>
            /// 总数
            /// </summary>
            public int TotalCount { get; set; }
            /// <summary>
            /// 总页数
            /// </summary>
            public int TotalPages { get; set; }
    
            /// <summary>
            /// 集合
            /// </summary>
            public dynamic DataList { get; set; }
        }
    }
    分页数据类

     2.3、分页实现类:

    namespace WebUI.PageinationService
    {
        /// <summary>
        /// 分页读取数据的实现类
        /// </summary>
        public class PageinationImplement
        {
            //数据库上下文实例
            private MyDbContext db;
    
            public PageinationImplement(MyDbContext dbContext)
            {
                this.db = dbContext;
            }
    
            /// <summary>
            /// 读取分页数据
            /// </summary>
            /// <typeparam name="T">实体</typeparam>
            /// <param name="pageinationInfo">分页信息类</param>
            /// <returns>分页数据</returns>
            public PageinationData GetPageinationData<T>(PageinationInfo pageinationInfo) where T : class
            {
                dynamic result = null;
                try
                {
                    #region SqlParameter参数
                    SqlParameter[] paras = new SqlParameter[8];
                    //页索引
                    paras[0] = new SqlParameter("pageIndex", DbType.Int32);
                    paras[0].Value = pageinationInfo.PageIndex;
                    //页大小
                    paras[1] = new SqlParameter("pageSize", DbType.Int32);
                    paras[1].Value = pageinationInfo.PageSize;                        
                    //表名
                    paras[2] = new SqlParameter("tableName", DbType.String);
                    paras[2].Value = pageinationInfo.TableName;
                    //查询字段
                    //EF仅支持返回返回某个表的全部字段,以便转换成对应的实体,无法支持返回部分字段的情况...???
                    paras[3] = new SqlParameter("fieldName", DbType.String);
                    paras[3].Value = pageinationInfo.FieldName;
                    //where条件
                    paras[4] = new SqlParameter("whereCondition", DbType.String);
                    paras[4].Value = pageinationInfo.WhereCondition;
                    //order条件
                    paras[5] = new SqlParameter("orderCondition", DbType.String);
                    paras[5].Value = pageinationInfo.OrderCondition;
                    //总数
                    paras[6] = new SqlParameter("totalCount", DbType.Int32);
                    paras[6].Value = pageinationInfo.TotalCount;
                    paras[6].Direction = ParameterDirection.Output;
                    //总页数
                    paras[7] = new SqlParameter("totalPages", DbType.Int32);
                    paras[7].Value = pageinationInfo.TotalPages;
                    paras[7].Direction = ParameterDirection.Output;
                    #endregion
    
                    string sql = "Procedure_SpiltPage @pageIndex,@pageSize,@tableName,@fieldName,@whereCondition,@orderCondition,@totalCount output,@totalPages output";
                    var list = db.Database.SqlQuery<T>(sql, paras).ToList();
    
                    PageinationData data = new PageinationData();
                    data.TotalCount= (int)paras[6].Value;
                    data.TotalPages= (int)paras[7].Value;
                    data.DataList = list;
    
                    result = data;
                }
                catch(Exception e)
                {
                    throw;
                }
    
                return result;
            }
        }
    }
    分页实现类

    3、调用并返回数据: 

    PageinationImplement pageImpl = new PageinationImplement(db);
    PageinationInfo pageination = new PageinationInfo();
    pageination.TableName = "NewsInfo";
    pageination.PageIndex = 1;
    pageination.PageSize = 15;
    pageination.FieldName = "*";
    pageination.OrderCondition = "PostTime desc";
    pageination.WhereCondition = "Isdelete=0";                
    var data = pageImpl.GetPageinationData<NewsInfo>(pageination);

    上面的new PageinationImplement(db)中的db是数据库上下文(DbContext实例),

    上面的data里包括了分页列表,总记录数,分页页数 信息。

    注:本来我执行存储过程,想只查询表的部分字段,结果会报错,暂时只能用*查询所有字段,

    网上查说EF暂时仅支持返回返回某个表的全部字段,以便转换成对应的实体,无法支持返回部分字段的情况...

    我能想到的方法就是自定义类,不用对应数据库的实体类。

    不知道有没有其他方法可以实现,各位大神如果有方法的话,希望指教一下,谢谢!

  • 相关阅读:
    Salesforce: 测试代码写在非测试类中
    Salesforce: 使用代码编辑日期时间
    测试用例练习
    DFA算法实现敏感词过滤
    基于redis实现分布式锁
    Python检查字符串之间的相似度
    二维码生成器
    MySQL 备份/恢复
    实现阿里云短信验证
    SnowFlake 生成唯一订单id
  • 原文地址:https://www.cnblogs.com/qk2014/p/6824103.html
Copyright © 2011-2022 走看看