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

ASP.NET MVC 三層架構擴展與 StructureMap 依賴注入實戰(Model 層篇)

     編輯:ASP.NET 基礎

系列目標

本系列將演示如何在 ASP.NET MVC 中構建低耦合的三層架構:Controller(表現層)→ Service(業務邏輯層)→ Repository(數據持久層),並使用 StructureMap 實現依賴注入(DI),使各層職責清晰、可測試、易擴展。首篇聚焦 Model 層與 EF 上下文的生命周期管理。

項目結構總覽

框架結構圖

Models 項目包含 EDMX 實體模型與核心上下文封裝 TYEntities。

Models 目錄結構

關鍵技術:EF 上下文的「請求級單例」模式

為了在同一 HTTP 請求或線程中共享同一個 ObjectContext(支援事務一致性),採用 HttpContext.Items + [ThreadStatic] 雙重保障策略。

TYEntities 核心代碼

using System;
using System.Web;

namespace TYStudioDemo.Models
{
    public partial class TYEntities
    {
        #region Fields
        const string ContextKey = "TYEntities";
        // 每個線程獨立實例,避免併發衝突
        [ThreadStatic]
        private static TYEntities _current;
        #endregion

        #region Properties
        public bool Disposed { get; set; }

        /// 
        /// Web 請求場景:從 HttpContext.Items 獲取或創建上下文
        /// 
        private static TYEntities ForWebRequest
        {
            get
            {
                var ctx = HttpContext.Current;
                if (ctx != null)
                {
                    var result = ctx.Items[ContextKey] as TYEntities;
                    if (result == null)
                    {
                        result = new TYEntities();
                        ctx.Items[ContextKey] = result;
                    }
                    return result;
                }
                return null;
            }
        }

        /// 
        /// 統一入口:優先 Web 請求上下文,否則回退到線程靜態實例
        /// 
        public static TYEntities Current
        {
            get
            {
                var result = ForWebRequest;
                if (result != null) return result;
                if (_current == null) _current = new TYEntities();
                return _current;
            }
        }
        #endregion

        #region Cleanup & Dispose
        /// 
        /// 請求結束時調用,釋放上下文資源
        /// 建議在 Global.asax Application_EndRequest 中統一調用
        /// 
        public static void Cleanup()
        {
            if (HttpContext.Current != null)
            {
                var result = HttpContext.Current.Items[ContextKey] as TYEntities;
                if (result != null)
                {
                    result.Dispose();
                }
                HttpContext.Current.Items[ContextKey] = null;
            }
            else if (_current != null)
            {
                _current.Dispose();
                _current = null;
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (!Disposed)
            {
                Disposed = true;
                Cleanup();
            }
            base.Dispose(disposing);
        }
        #endregion
    }
}

為什麼這樣設計?

場景獲取方式生命周期管理
Web 請求TYEntities.Current → ForWebRequestHttpContext.Items 隔離請求,Application_EndRequest 統一 Cleanup
後台任務/測試/非 Web 線程TYEntities.Current → _current[ThreadStatic] 隔離線程,手動調用 Cleanup() 或 using 等價模式

關鍵注意事項

  • 嚴禁 using 包裹:TYEntities.Current 返回的是共享實例,using 會提前 Dispose 導致後續代碼報錯。
  • EDMX 代碼生成策略:刪除 .tt 模板,將 Code Generation Strategy 從 None 改為 Default,獲得傳統 ObjectContext 衍生類與實體類,便於擴展分部類。
  • 事務一致性:同一請求/線程內所有 Repository 共享同一 Context,天然支援跨 Repository 的事務操作。

Global.asax 整合示例

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_EndRequest(object sender, EventArgs e)
    {
        TYStudioDemo.Models.TYEntities.Cleanup();
    }
}

下一步預告

下一篇將介紹 Repository 層接口設計、泛型基類實現,以及如何將 Repository 注入 Service、Service 注入 Controller,完成 StructureMap 容器配置與約定式註冊。

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