測試環境建立
USE Test;
IF EXISTS (SELECT * FROM sysobjects WHERE id = OBJECT_ID('R_Student') AND type = 'U')
DROP TABLE R_Student;
CREATE TABLE R_Student (
Id NVARCHAR(64) PRIMARY KEY,
Class NVARCHAR(64) NOT NULL,
Age TINYINT NOT NULL,
Sex TINYINT NOT NULL
);
DECLARE @i INT = 0;
WHILE @i < 1000000
BEGIN
INSERT R_Student VALUES ('Name'+STR(@i), 'Class'+STR(@i), @i%100, @i%2);
SET @i += 1;
END
DataReader 分頁核心邏輯
public DataSet RangeQuery(string queryString, long first, long last)
{
try
{
OpenDataReader(queryString); // 執行命令,取得 DataReader
if (first < 0) first = 0;
// 1. 略過前 (first) 筆:只移動指標,不讀取資料
for (long i = 0; i < first; i++)
if (!_DataReader.Read()) return _SchemaDataSet;
if (last < 0) last = long.MaxValue;
// 2. 讀取目標範圍資料
for (long i = first; i <= last; i++)
{
DataRow row = NextRow(); // 內部呼叫 _DataReader.Read() 並轉換
if (row != null) _SchemaTable.Rows.Add(row);
else break;
}
return _SchemaDataSet;
}
finally { CloseDataReader(); }
}
原理優勢
- 略過階段不傳輸資料:
DataReader.Read() 僅移動內部指標,網路傳輸量極小。
- 記憶體友善:僅將目標頁面資料載入
DataTable。
- 無需撰寫動態 SQL:邏輯在用戶端控制,資料庫只負責排序與串流。
適用場景與限制
- 適用:WinForms/WPF 等保持連線的智慧型用戶端、報表匯出、ETL 批次處理。
- 不適用:ASP.NET 等無狀態 Web 應用 (連線無法跨請求保持)。