2

我不擅長sql,但我必須在我的存儲過程中有很多記錄的jqGrid進行分頁。我的asp.net MVC3控制器代碼如下,如何在存儲過程中爲jqGrid尋呼?

[HttpPost] 
    public JsonResult GetExtraPersons(int cId, long pId, JQGridSettings gridSettings) 
    { 
     List<ExtraPerson> extraPersons = new List<ExtraPerson>();    
     ExtraPersonViewModel extraPersonViewModel = new ExtraPersonViewModel(); 
     extraPersonViewModel.CampId = cId; 
     extraPersonViewModel.ReferencePatientId = pId; 

     extraPersons = ExtraPersonService.GetExtraPersons(extraPersonViewModel.CampId, extraPersonViewModel.ReferencePatientId); 

     int pageIndex = gridSettings.pageIndex; 
     int pageSize = gridSettings.pageSize; 
     int totalRecords = extraPersons.Count; 
     int totalPages = (int)Math.Ceiling((float)totalRecords/(float)pageSize); 

     int startRow = (pageIndex - 1) * pageSize; 
     int endRow = startRow + pageSize; 

     var jsonData = new 
     { 
      total = totalPages, 
      page = pageIndex, 
      records = totalRecords, 
      rows = 
      (
       extraPersons.Select(e => new 
       { 
        Id = e.ExtraPersonId,     
        FirstName = e.FirstName, 
        LastName = e.LastName, 
        MobilePhone = e.MobileNumber, 
        Email = e.EmailId, 
        PersonalNumber = e.PersonNumber, 
        Diabetes = e.Diabetes, 
        BloodPressure = e.BloodPressure, 
       }) 
      ).ToArray() 
     }; 
     return Json(jsonData); 
    } 

以及如下SQL Server 2008中我的存儲過程,

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER PROCEDURE [dbo].[GetExtraPerson] 
(
@CampId INT, 
@ReferencePatientId BIGINT 
) 


AS 

BEGIN 
SET NOCOUNT ON   

SELECT 

PERS.PersonId, 
PERS.FirstName, 
PERS.LastName, 
PERS.MobileNumber, 
PERS.EmailId, 
PERS.PersonNumber, 
E.ExtraPersonId, 
E.Diabetes, 
E.BloodPressure 

FROM 
ExtraPerson E 
INNER JOIN Person PERS 
ON PERS.PersonId=E.PersonId 



WHERE [email protected] AND [email protected] AND E.IsDeleted = 0 
END 

現在的jqGrid是除了分頁正常工作。例如:如果它有15條記錄,第一頁顯示10條記錄,剩餘的位於第二頁,但我不能去它。 任何人都可以建議我,如何爲jqgrid進行分頁?

回答

2

有很多方法可以實現您需要的STORED PROCEDURE。例如,您可以在CTE SQL語句中使用ROW_NUMBER構造。

如果您使用SQL Server 2012,則可以在ORDER BY之後使用OFFSETFETCH來實現分頁(請參見here)。如果SQL語句看起來非常接近使用OFFSETLIMIT的相應MySQL或PostgreSQL語句。順便說一句,Microsoft Entity Framework使用Entity SQL Language具有相近的構造(SKIPLIMIT)。如果您使用SQL Server 2012或更高版本,則可能需要OFFSETFETCH

因爲你在你的問題中包含SQL Server 2008標記,所以我不會在我的答案中使用新的SQL Server 2012結構。

另一個更好的方法是使用sp_executesql,它允許您使用參數構造一個帶有字符串的SQL語句。它允許重用對於最佳性能非常重要的執行計劃。該方法允許您擴展STORED PROCEDURE的代碼以實現服務器端過濾(搜索)。

我看到需要在包含返回數據的ID的SQL語句中實現分頁(在您的情況下爲PersonId)。所以我決定建議您使用SELECT TOP結合LEFT OUTER JOIN的簡化方式。

STORED PROCEDUREdbo.GetExtraPerson可以int類型的兩個附加參數:@skip@pageSize。在@skip情況下等於0STORED PROCEDURE可以只執行

SELECT TOP (@pageSize) PERS.PersonId 
    ,PERS.FirstName 
    ,PERS.LastName 
    ,PERS.MobileNumber 
    ,PERS.EmailId 
    ,PERS.PersonNumber 
    ,E.ExtraPersonId 
    ,E.Diabetes 
    ,E.BloodPressure 
FROM ExtraPerson E 
    INNER JOIN Person PERS ON PERS.PersonId=E.PersonId 
WHERE [email protected] AND [email protected] AND E.IsDeleted=0 

如果@skip不等於0那麼相應的SQL語句可以是下列

WITH GetAll AS (
    SELECT PERS.PersonId 
     ,PERS.FirstName 
     ,PERS.LastName 
     ,PERS.MobileNumber 
     ,PERS.EmailId 
     ,PERS.PersonNumber 
     ,E.ExtraPersonId 
     ,E.Diabetes 
     ,E.BloodPressure 
    FROM ExtraPerson E 
     INNER JOIN Person PERS ON PERS.PersonId=E.PersonId 
    WHERE [email protected] AND [email protected] AND E.IsDeleted=0 
),GetFirst AS (
    SELECT TOP (@skip) * 
    FROM GetAll 
    ORDER BY Name 
),GetNext AS (
    SELECT TOP (@pageSize) a.* 
    FROM GetAll AS a 
     LEFT OUTER JOIN GetFirst AS f ON f.Id=a.Id 
    WHERE f.Id IS NULL 
    ORDER BY Name 
) 
SELECT * FROM GetNext 

dbo.GetExtraPerson完整的代碼可能是關於以下內容

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE dbo.GetExtraPerson 
    @CampId int, 
    @ReferencePatientId bigint, 
    @skip int, 
    @pageSize int 
AS 
BEGIN 
    DECLARE @records int; 
    SET NOCOUNT ON; 

    SET @records = (SELECT COUNT(*) 
        FROM ExtraPerson E 
         INNER JOIN Person PERS ON PERS.PersonId=E.PersonId 
        WHERE [email protected] 
         AND [email protected] 
         AND E.IsDeleted=0); 

    IF @skip <= 0 
     SELECT TOP (@pageSize) PERS.PersonId 
      ,PERS.FirstName 
      ,PERS.LastName 
      ,PERS.MobileNumber 
      ,PERS.EmailId 
      ,PERS.PersonNumber 
      ,E.ExtraPersonId 
      ,E.Diabetes 
      ,E.BloodPressure 
     FROM ExtraPerson E 
      INNER JOIN Person PERS ON PERS.PersonId=E.PersonId 
     WHERE [email protected] AND [email protected] 
      AND E.IsDeleted=0 
    ELSE 
     WITH GetAll AS (
      SELECT PERS.PersonId 
       ,PERS.FirstName 
       ,PERS.LastName 
       ,PERS.MobileNumber 
       ,PERS.EmailId 
       ,PERS.PersonNumber 
       ,E.ExtraPersonId 
       ,E.Diabetes 
       ,E.BloodPressure 
      FROM ExtraPerson E 
       INNER JOIN Person PERS ON PERS.PersonId=E.PersonId 
      WHERE [email protected] AND [email protected] 
       AND E.IsDeleted=0 
     ),GetFirst AS (
      SELECT TOP (@skip) * 
      FROM GetAll 
      ORDER BY Name 
     ),GetNext AS (
      SELECT TOP (@pageSize) a.* 
      FROM GetAll AS a 
       LEFT OUTER JOIN GetFirst AS f ON f.Id=a.Id 
      WHERE f.Id IS NULL 
      ORDER BY Name 
     ) 
     SELECT * FROM GetNext; 

    RETURN @records; 
END 
GO 

上述過程返回th e額外記錄總數,您可以使用它來指定totalRecords值。

,如果您結合使用上面的代碼與sp_executesql你可以很容易修改代碼,以包括所有SELECT TOP聲明ORDER BY使返回的值將對應於排序順序由jqGrid的用戶請求。

+0

感謝您的簡要回答。我總是懷疑你的簡短答案。 – prakash2089

+0

@Prakash:不客氣!我希望我的回答能幫助你實現你的要求。 – Oleg

+0

我在控制器中進行了以下更改extraPersonViewModel.PageSize = gridSettings.pageSize; extraPersons = ExtraPersonService.GetExtraPersons(extraPersonViewModel.CampId,extraPersonViewModel.ReferencePatientId,extraPersonViewModel.PageSize); – prakash2089