此文講述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暫時僅支持返回返回某個表的全部字段,以便轉換成對應的實體,無法支持返回部分字段的情況...
我能想到的方法就是自定義類,不用對應數據庫的實體類。
不知道有沒有其他方法可以實現,各位大神如果有方法的話,希望指教一下,謝謝!