在維護企業內部 EIP 系統的過程中,曾經歷幾次明確的架構轉向與效能瓶頸。這篇文章記錄我實際參與與理解的系統演進過程,從 MVC 架構的調整,到查詢策略與資料存取的選擇,背後其實反映的是不同開發階段的取捨與策略。
一開始,系統是以 ASP.NET 的 MVC 架構開發。這種做法確實有結構分明的好處,開發與維護也更容易分工。不過在實務操作中,我們注意到幾個效能痛點:
為了讓流程更輕巧,團隊決定在非核心流程中改用 WebForm 與簡化結構:一頁中直接撰寫資料查詢與畫面處理邏輯。
早期系統中,為了保持物件封裝清晰,我們曾採用「逐筆查詢」的作法。每筆列表資料都會轉為一個物件實例,並對資料庫執行一筆 SELECT 查詢,例如顯示 100 筆申請資料就執行 100 次 SQL。
這個作法帶來以下缺點:
後來調整為「一次查整包」的方式,只對主列表執行一次 SQL 查詢:
SELECT id, name, status, created_at FROM flow_request WHERE ...
若使用者點選「查看詳細資料」才個別查詢,稱為「延遲查詢」策略。
📌 仍適合採用逐筆查詢的情境:
使用條件 | 建議查詢方式 |
---|---|
資料筆數少(例如 < 20 筆) | 逐筆查詢 |
每筆需額外格式處理或封裝 | 逐筆封裝清晰 |
即時更新(如帳戶餘額) | 每次查詢取得最新資料 |
記憶體有限或需串流 | 逐筆查詢搭配迴圈 |
我們也保留了如 GetRequestDetailById(id)
這類的查詢方法,用於導出或進階查詢,達到彈性與效能間的平衡。
系統中有兩套資料存取物件:
儘管 DBHelper 較佳,但舊模組仍大量使用 DAL,因此我們建立 SafeDAL
類別進行輸入過濾。
密碼採用不可逆的雜湊(如 SHA256)儲存,登入時會將輸入密碼雜湊後與資料庫中 password_hash
比對。
🧪 登入驗證流程:
password_hash
比對。✅ 好處:
🔁 重設密碼時會將其設為預設值(如 9999
),加密後存入,使用者下次登入會強制修改。
📌 延伸建議:
last_changed
, retry_count
, is_locked
等欄位加強安全。送審資料先寫入 flow_approver_temp
,流程完成後再移至 flow_approver_his
。
✅ 好處:
部門結構會影響簽核流程與主管遞補,我們從 ERP 同步部門資料後,也提供以下彈性:
📌 實作方式:
is_virtual = Y
總公司
└─ 研發部(實體)
├─ 研發一組(虛擬)
├─ 研發二組(虛擬)
🛡️ 並記錄調整 log,可一鍵還原前層級。
我們在呈現請假流程狀態時,使用自訂 HTML,而非 GridView 等控制項:
<table>
<tr>
<td>節點名稱</td>
<td>簽核人</td>
<td>狀態</td>
</tr>
</table>
✅ 優點:
⚠️ 缺點:
維護大型 WebForm 專案時,我通常採「由畫面反查邏輯」的方式:
gvFlow
, btnSubmit
這樣可以快速找到核心程式碼,不需讀完整支程式。
我的系統原本採用 MVC 架構,但效能不佳,轉為單一頁面是否更合適?
如何改善逐筆查詢造成的效能瓶頸?是否能改成延遲查詢?
我使用 DAL 串接資料庫,但沒有參數化查詢,要如何降低 SQL injection 風險?
在 ASP.NET WebForm 中,手刻 HTML 與使用控制項各有什麼利弊?