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

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

為了在同一 HTTP 請求或線程中共享同一個 ObjectContext(支援事務一致性),採用 HttpContext.Items + [ThreadStatic] 雙重保障策略。
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 → ForWebRequest | HttpContext.Items 隔離請求,Application_EndRequest 統一 Cleanup |
| 後台任務/測試/非 Web 線程 | TYEntities.Current → _current | [ThreadStatic] 隔離線程,手動調用 Cleanup() 或 using 等價模式 |
TYEntities.Current 返回的是共享實例,using 會提前 Dispose 導致後續代碼報錯。Code Generation Strategy 從 None 改為 Default,獲得傳統 ObjectContext 衍生類與實體類,便於擴展分部類。public class MvcApplication : System.Web.HttpApplication
{
protected void Application_EndRequest(object sender, EventArgs e)
{
TYStudioDemo.Models.TYEntities.Cleanup();
}
}
下一篇將介紹 Repository 層接口設計、泛型基類實現,以及如何將 Repository 注入 Service、Service 注入 Controller,完成 StructureMap 容器配置與約定式註冊。