RDIFramework.NET 是基於 .NET 的企業級快速開發框架,內建強大的分頁抽象層,支援多種資料庫 (SQL Server, Oracle, MySQL, PostgreSQL 等) 的自動分頁 SQL 生成。本文以「入庫主表 + 明細表」多表關聯查詢為例,展示如何通過**臨時表表達式**配合框架 GetDTByPage 方法,零手寫分頁 SQL 實現高效分頁。
<table id="list1"></table>
<script type="text/javascript">
$(function () {
autoResize({ dataGrid: '#list1', gridType: 'datagrid', callback: grid.bind, height: 0 });
$('#a_add').click(CRUD.add);
$('#a_edit').click(CRUD.edit);
$('#a_delete').click(CRUD.del);
});
var grid = {
bind: function (winSize) {
$('#list1').datagrid({
url: '/demo/handler/ProductIn.ashx?action=GetMultiPage', // 後端分頁接口
toolbar: '#toolbar',
title: "數據列表",
iconCls: 'icon icon-list',
width: winSize.width,
height: winSize.height,
nowrap: false,
rownumbers: true,
striped: true,
idField: 'ID',
sortName: 'CREATEON',
sortOrder: 'desc',
singleSelect: true,
frozenColumns: [[]],
columns: [[
{ title: '主鍵', field: 'ID', width: 120, hidden: true },
{ title: '入庫單編碼', field: 'CODE', width: 130 },
{ title: '入庫日期', field: 'INDATE', width: 150 },
{ title: '入庫類型', field: 'INTYPE', width: 100 },
{ title: '保管員', field: 'CUSTODIAN', width: 70 },
{ title: '品名', field: 'FULLNAME', width: 100 },
{ title: '數量', field: 'AMOUNT', width: 80 },
{ title: '單價', field: 'UNITPRICE', width: 150 }
]],
pagination: true,
pageSize: 5,
pageList: [5, 10, 20]
});
},
getSelectedRow: function () { return $('#list1').datagrid('getSelected'); },
reload: function () { $('#list1').datagrid('clearSelections').datagrid('reload', { filter: '' }); }
};
</script>
public class ProductIn : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string action = context.Request["action"];
switch (action)
{
case "GetMultiPage":
context.Response.Write(GetProductMultiPage());
break;
// 其他 action...
}
}
private string GetProductMultiPage()
{
var returnJson = "[]";
var managerMain = new CASE_PRODUCTIN_MAINManager(this.dbHelper, Utils.UserInfo);
int pageIndex = pageindex > 0 ? pageindex : 1;
int pageSize = pagesize > 0 ? pagesize : 20;
int recordCount;
// 核心:將多表 JOIN 寫為子查詢/衍生表,作為「虛擬表」傳給分頁方法
managerMain.CurrentTableName = @"
(SELECT tab1.ID, tab1.CODE, tab1.INDATE, tab1.INTYPE, tab1.CUSTODIAN, tab1.CREATEON,
tab2.FULLNAME, tab2.AMOUNT, tab2.UNITPRICE
FROM dbo.CASE_PRODUCTIN_MAIN tab1
INNER JOIN dbo.CASE_PRODUCTIN_DETAIL tab2 ON tab1.ID = tab2.CASE_PRODUCTIN_MAIN_ID) pageData";
managerMain.SelectField = "*"; // 查詢所有欄位
// 框架自動生成分頁 SQL (如: SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY CREATEON DESC) AS RN, * FROM pageData) T WHERE RN BETWEEN ...)
var dtProductIn = managerMain.GetDTByPage(out recordCount, pageIndex, pageSize, null, "CREATEON DESC");
if (dtProductIn != null && dtProductIn.Rows.Count > 0)
{
returnJson = JSONhelper.FormatJSONForEasyuiDataGrid(recordCount, dtProductIn);
}
return returnJson;
}
public bool IsReusable { get { return false; } }
}
GetDTByPage(out recordCount, pageIndex, pageSize, condition, orderBy) 內部:
SELECT COUNT(1) FROM {CurrentTableName} WHERE {condition} 獲取總記錄數 recordCount。OFFSET ... ROWS FETCH NEXT ... ROWS ONLYROW_NUMBER() OVER (ORDER BY ...) 子查詢ROWNUM 雙層嵌套LIMIT ... OFFSET ...DataTable。CurrentTableName)、排序欄位,框架自動處理各資料庫方言差異。Manager 基類提供強型別 CRUD,結合 CurrentTableName 臨時覆寫,保持代碼整潔。{total:..., rows:[...]}),前端零適配。| 場景 | 建議方案 |
|---|---|
| 中小數據量 (≤ 10萬行)、多表 JOIN、動態排序/篩選 | 本文方案:衍生表 + 框架分頁 |
| 大數據量、高頻查詢、固定查詢模式 | 建立索引視圖 / 物化視圖 / 彙總表,直接分頁查視圖 |
| 跨資料庫異構查詢 | 框架支援多資料庫,但分頁 SQL 生成需針對目標庫測試 |
| 複雜多層 JOIN、聚合、窗口函數 | 將複雜邏輯封裝為資料庫視圖/函數,框架直接分頁查視圖 |
RDIFramework.NET 的分頁抽象層極大降低了多表關聯分頁的開發門檻:只需將 JOIN 查詢寫成子查詢賦值給 CurrentTableName,即可獲得跨資料庫、自動計數、標準 JSON 輸出的分頁能力。這體現了優秀框架「約定優於配置、封裝變化點」的設計智慧,讓開發者專注於業務邏輯而非分頁 SQL 繁瑣細節。