2011-04-07 49 views
2

我的公司使用專門通過存儲過程填充的原始未定型數據集。我的任務是找到一種方法來檢索非常大的結果集(分頁)以及獲取延遲加載功能的方法(至少我認爲這是懶加載;我仍然在學習這些東西),所以我們不是在一批中拉回成千上萬行並佔用服務器資源。使用DataSets處理分頁和「延遲加載」?

我個人對DataSets並不熟悉,因爲我儘可能避免使用它們,而且我寧願在這裏完全擺脫它們,但是說「更改所有使用LINQ/EF」並不是一個有效的答案因爲對管理沒有商業價值(並且重做事情需要很長時間,所以這個想法會立即被擊落)。

是否有一些資源可以查看獲得相同類型的功能,但使用標準的非類型化數據集?

編輯:另外,我需要一個解決方案,可以使用動態創建的SQL,不使用存儲過程。

+0

關於術語,我傾向於使用「分頁」來描述您需要的功能; 「延遲加載」我已經習慣於描述更復雜的對象圖/模型的部分初始加載,接下來是根據需要按需加載圖的其他部分。 [我沒有這方面的參考,所以它可能只是我...] – richaux 2011-04-07 13:01:56

+0

順便說一句,避免DataSets就像避免'bool'或'int'。一個DataSet就是它 - 數據庫數據的一個精心編寫的,100%可靠的通用內存中表示,它在很多不同情況下都非常有用。然而,公平地說,我絕對不會將它們用於高流量的網站。 – MusiGenesis 2011-04-07 13:04:30

+0

我一直使用Lazy Loading來表示「直到我真正需要它時才執行此操作」,但作爲我的經理所說的要求是「延遲加載」,所以我在這裏使用了:)關於DataSets I同意,但我認爲有更好的解決方案,有幾個情況下DataSet是比替代方案更好的選擇。 – 2011-04-07 13:05:38

回答

2

您需要在存儲過程中實現分頁。我假設你正在使用SQL Server,所以這裏是一個鏈接:

http://www.davidhayden.com/blog/dave/archive/2005/12/30/2652.aspx

注意,這無關與數據集本身。據推測,你的代碼從存儲過程調用中生成一個DataSet。如果您重寫您的proc進行分頁,那麼您的代碼將生成一個僅包含請求的頁面記錄的DataSet。

您可以使用原始proc返回的數據集來實現分頁,方法是緩存DataSet並僅將所選行返回給客戶端(或者更準確地說,僅使用DataSet的選定行來生成客戶端HTML),但這是一個超級騙子,真的很不好的想法。

-1

您可以看看Value List Handler模式,該模式設計用於「客戶需要一系列項目......以便進行演示」。列表中的項目數量未知,並且在許多情況下可能非常大「。

示例(在上面的鏈接和here)是用於Java的,但應該相當容易地轉換爲asp.net。

+0

希望人們會說爲什麼他們會投下一些東西;這是一個不錯的建議,當我有更簡單的方法(請參閱其他答案)時,我可以想到這件事情有點複雜,但沒有理由讓自己陷入低谷。 – 2011-04-07 13:03:59

+0

-1來自我。兩個問題:1)這是C#,而不是Java;和2)*模式*不是實際的解決方案。如果我已經喝過咖啡了,我可能不會打擾下來投票。 – MusiGenesis 2011-04-07 13:08:29

+0

不用擔心,只是好奇:) – 2011-04-07 13:14:00

1

我有與asp.net 2.0網站相同的問題,沒有「延遲加載」的解決方案。爲了對數據集進行分頁,我使用了2個sprocs,它將幫助我在每個選擇中都包裝分頁功能。

CREATE PROCEDURE [dbo].[Generic_Counting] 
    @tables VARCHAR(MAX), 
    @filter VARCHAR(MAX) = '1=1'  
AS 
BEGIN 
    SET NOCOUNT ON; 


    DECLARE @strQuery VARCHAR(8000) 

    SET @strQuery = ' SELECT COUNT(*) FROM '+ @tables +' 
      WHERE '+ @filter 

    execute  (@strQuery) 
    IF @@ERROR<>0 
    BEGIN 
     --error on generic count 
     SET NOCOUNT OFF 
     RETURN 10067 
    END 

    SET NOCOUNT OFF 
    RETURN 0 
END 
GO 

CREATE PROCEDURE [dbo].[Generic_Paging] 
    @tables VARCHAR(1000), 
    @pk VARCHAR(100), 
    @pageNumber INT = 1, 
    @pageSize INT = 10, 
    @fields VARCHAR(MAX) = '*', 
    @filter VARCHAR(MAX) = '1=1', 
    @orderBy VARCHAR(MAX) = NULL 
AS 
BEGIN 
    SET NOCOUNT ON; 
    DECLARE @strQuery VARCHAR(8000) 
    DECLARE @strMinRecord VARCHAR(12); 
    DECLARE @strMaxRecord VARCHAR(12); 

    SET @strMinRecord = CONVERT(VARCHAR(12),((@pageNumber -1)*@pageSize + 1)) 
    SET @strMaxRecord = CONVERT(VARCHAR(12), (@pageNumber * @pageSize)) 

     -- Use ROW_NUMBER function 

    SET @strQuery =' 
    WITH Generic_CTE As 
    (
     SELECT ''RowNumber'' = ROW_NUMBER() OVER(ORDER BY ' + 
     ISNULL(@orderBy,@pk) +'),' + 
     @fields + 
     ' FROM ' + @tables + 
     ' WHERE ('+ @filter +') 
    ) 
    SELECT ' + @fields + ' 
    FROM Generic_CTE 
    WHERE RowNumber BETWEEN ' + @strMinRecord +' AND '+ @strMaxRecord 



    --print @strQuery 
    execute (@strQuery) 

    IF @@ERROR<>0 
    BEGIN 
     --error on generic paging 
     SET NOCOUNT OFF 
     RETURN 10066 
    END 
    SET NOCOUNT OFF 
    RETURN 0 
END 
GO