首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

ASP.NET MVC 校友錄實戰(二):實體模型設計演進與踩坑記

     編輯:關於.NET

本篇回顧實體模型從設計到落地的演進過程,分享開發過程中遇到的 Code First 遷移難題、Cookie 驗證機制探索、權限控制架構抉擇等實戰經驗。

一、開發前的技術預研

專案啟動前,針對核心技術點進行 Spike 測試:

  • 權限控制:比較 `Filter` vs 基底 Controller 繼承
  • 登入狀態:Session vs Cookie vs FormsAuthentication 整合
  • Code First 遷移:自動遷移 vs 手動遷移、種子資料策略
  • 檔案上傳:實體檔案 vs 資料庫二進位儲存

「先探路,後過兵」—— 預先驗證技術可行性,避免正式開發時被卡關。

二、模型設計初版與調整

初版 ER 圖

初版資料庫模型設計圖

關鍵調整決策

原設計調整後理由
User 表包含所有欄位拆分 User(認證) + UserInfo(資料)登入高頻查詢輕量化、支援延遲載入
School 使用 Id 主鍵School 使用 Name 天然主鍵學校名稱唯一,減少 Join、簡化前端下拉綁定
Class 使用複合主鍵Class 改用 Identity ClassIdEF 對複合鍵支援較弱、URL 路由更簡潔
多對多關聯建立中介實體保留中介實體並豐富屬性記錄加入時間、角色(幹部/成員)、審核狀態

三、Code First 遷移踩坑與解決

問題:模型變更導致資料庫不一致

初期使用 `Database.SetInitializer(new DropCreateDatabaseIfModelChanges())`,資料全失。

解決方案:手動遷移 + 種子資料

  1. 關閉自動遷移:`AutomaticMigrationsEnabled = false`
  2. 每次模型變更執行 `Add-Migration "描述性名稱"`
  3. 編輯生成的遷移類別,在 `Up()` 中添加種子資料:
public partial class AddSchoolTable : DbMigration
{
    public override void Up()
    {
        CreateTable(...);
        // 種子資料
        Sql("INSERT INTO Schools (Name) VALUES ('國立臺灣大學'), ('國立清華大學')");
    }
    public override void Down() { DropTable("Schools"); }
}

遷移腳本納入版控

團隊協作時,遷移檔案(`Migrations/20240101120000_AddSchoolTable.cs`)必須 Commit,新成員 `Update-Database` 即可同步結構。

四、Cookie 驗證機制探索

問題:Redirect 後 Session 遺失

早期嘗試在 `Controller` 基底類別寫 `OnActionExecuting` 檢查 Session,但 `RedirectToAction` 導致新請求 Session 為空。

根因與解決

  • Session 預設 InProc 模式,應用程式池回收即失效
  • 改用 `FormsAuthentication` + 永久 Cookie 儲存加密 Ticket
  • 自訂 `IPrincipal` 實現角色權限,`Global.asax` 中 `Application_PostAuthenticateRequest` 解析 Ticket 重建 Principal

五、權限控制架構抉擇

方案 A:基底 Controller + 虛擬方法

public class BaseController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        CheckPermission(filterContext);
        base.OnActionExecuting(filterContext);
    }
}

缺點:VS 建立 Controller 預設繼承 `Controller`,每次需手動改繼承 `BaseController`,違背慣例。

方案 B:ActionFilterAttribute(最終採用)

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class RequireLoginAttribute : ActionFilterAttribute { ... }

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class RequireAdminAttribute : ActionFilterAttribute { ... }

優點:屬性裝飾式、符合 MVC 慣例、可精確控制到 Action 層級、不干擾 Controller 繼承鏈。

六、開發工具與協作

  • 版本控制:Git + GitHub(私有倉庫)
  • 資料庫版本:Code First Migrations 檔案納入 Git
  • 問題追蹤:GitHub Issues + Projects 看板
  • 文檔:README + Wiki 記錄架構決策

七、心得與建議

  1. 模型先行:花時間設計 ER 圖,雖然會調整,但核心聚合根要穩定
  2. 預研要實際跑 Code:文檔只能參考,實際寫 Demo 才能發現坑
  3. 遷移要有紀律:每次模型變更產生遷移檔,禁止直接修改資料庫
  4. 慣例優於配置:遵循 MVC/EF 慣例,減少樣板代碼

畢業專題雖小,但完整經歷了「需求→設計→預研→開發→遷移→部署」全生命週期,比單純 CRUD 練習收穫大得多。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved