寫老式的ADO.NET程式的人都知道一定要這麼做 !
在ASP.NET MVC應用程式中, DbContext 實例基本上是在 Controller 中使用, 一些基礎知識說明 MVC 的 controllers 在當請求(request)到達時被建立, 然後在請求已經完成時被 dispose (are disposed), 在 ASP.NET MVC中如何確認 DbContext 實例被 dispose (is disposed)?
方法1 : 使用 Using 區塊
using (EmployeeContext context = new EmployeeContext())
{
return View(context.Employees.ToList());
}
使用 using 區塊可以確保, 當執行到區塊底部時, EmployeeContext 會被 dispose (is disposed), using 區塊是 try{...}finally{...} 的簡寫方式(語法糖), context (DbContext 實例)會在 finally 裡面被 dispose (is disposed), 這區塊會確保 context 被 dispose (is disposed), 但是這樣很難在應用程式中的不同地方分享同一個 context, 會發現自己一直在建立更多要使用的 DbContext 實例, 這也使自己的 Controller 裡出現邏輯處理之外的雜訊, 即使比使用 try finally 乾淨多了, 但是依然感覺一些雜訊存在
方法2 : Dispose 區塊
另一種方法是在 controller 中實作 disposepublic class EmployeeController : Controller
{
private EmployeeContext _context;
public EmployeeController()
{
_context = new EmployeeContext();
}
public ActionResult Index()
{
return View(_context.Employees.ToList());
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_context.Dispose();
}
base.Dispose(disposing);
}
}
當請求完成時, controller 會被dispose (is disposed), 這方式也確保了 EmployeeContext 也被dispose (is disposed); 和 using 區塊很像, 在Controller裡產生了雜訊並且很難在應用程式中不同的地方分享同一個實例, 這方法並且依賴團隊中的所有開發人員要正確的實作 dispose
方法3 : 依賴注入 (Dependency Injection)
public class EmployeeController : Controller { private EmployeeContext _context; public EmployeeController(EmployeeContext context) { _context = context; } public ActionResult Index() { return View(context.Employees.ToList()); } }
這方法解除了 controller 對 DbContext 實例的生命週期的責任. controller 要求一個 DbContext 實例, 但是不需要關心這實例從哪裡來或是當她結束的時候會去那裡?我們知道這個 Controller 中只有一個建構子, 所以建立 EmployeeController 必須傳入一個 EmpolyeeContext 實例, 所以 Controller 不用再負責建立 DbContext, 意思說也不再需要去 dispose !但是如果 Controller 不用再去建立 context, 那誰該去建立? 我們如何確認 context 真的被 dispose (is being disposed)?用 IoC 容器解決這問題!nuget上有很多 injection/IoC 容器, 例如 NInject, 大致流程是註冊使用 NInject 的 OnPerRequestHttpModule 並設置要用來產生實例的 DbContext(例如範例中的 EmpolyeeContext), 經過這些設置後, NInject 將會認出你的 Controller 所要求的實例(例如 EmpolyeeContext 的實例), 然後執行以下流程:1. 每次 Http Request 時建立實例2. 傳送實例到 Controller 建構子3. Http Request 結束時 dipose 實例OnPerRequestHttpModule 的預設行為:每次 Http Request 都建立一個新的 EmpolyeeContext 實例(context), 這表示不同的 Request 無法使用同一個 context, 也保證不會產生兩個以上的 EmpolyeeContext 被建立, 即使最後請求經過了三個都要求同一個 EmpolyeeContext 的 Controllers, 換句話說, context 的生命週期和 request 的生命週期綁在一起
沒有留言:
張貼留言