總目錄:ASP.NET MVC5 及 EF6 學習筆記 - (目錄整理)html
上一篇:EF學習筆記(八):更新關聯數據web
本篇原文:Async and Stored Procedures數據庫
爲什麼要採用異步?windows
一個Web服務器確定有可用線程的限制,那麼在一些訪問量特別大的狀況下,線程確定會消耗完;這個時候服務器確定處理不了請求,必須等線程裏處理結束才能夠處理請求;安全
在非異步的時候,不少線程都處於等待狀態,並非一直在工做,而是在等相似於I/O等處理結束;服務器
採用異步的時候,當一個處理在等待I/O處理結束的時候,能夠先去作作其餘事情;多線程
因此異步處理可使服務器更爲高效,較低延遲的狀況下處理更多的請求。mvc
在早期的.NET中,寫或者測試異步處理都是很複雜的,慶幸的是.NET 4.5之後寫或者測試異步處理請求代碼都很是簡單,除非有特別的理由不採用異步處理;app
異步處理確實會有一些多出來的系統開銷,對於低流量的應用,效果能夠忽略,但對於大流量的應用,效果是很明顯的;異步
更專業的資料: Use .NET 4.5's async support to avoid blocking calls.
下面作些代碼測試:
採用異步方式新建Department控制器:
自動生成的Index Action:
public async Task<ActionResult> Index()
{
var departments = db.Departments.Include(d => d.Administrator);
return View(await departments.ToListAsync());
}
與非異步方式,有4處不一樣來實現EF異步請求數據:
一、請求方法加上了async標誌關鍵字,等於告訴編譯器這個方法中有部分方法體爲異步的,須要生成針對部分方法體的異步回調,而且自動建立一個Task<ActionResult>對象做爲異步返回;
二、返回類型從ActionResult變爲Task<ActionResult>,Task<T>代表後續處理將使用T類型;
三、await
關鍵字引用於Call Web Service,當編譯器看到await這個關鍵字,就會把這個方法分爲兩部分,第1部分就是開始異步處理,第2部分就是異步處理完成後,再回調的部分;
四、採用ToList的異步版本方法;
(原文後面一段沒看明白。。。感受有些筆誤以及思路沒理清楚)
接後面改幾個視圖,把Index視圖裏稍微改下,顯示Administrator的全名:
@model IEnumerable<EFTest.Models.Department> @{ ViewBag.Title = "Departments"; } <h2>Departments</h2> <p> @Html.ActionLink("Create New", "Create") </p> <table class="table"> <tr> <th> @Html.DisplayNameFor(model => model.Name) </th> <th> @Html.DisplayNameFor(model => model.Budget) </th> <th> @Html.DisplayNameFor(model => model.StartDate) </th> <th> Administrator </th> <th></th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Name) </td> <td> @Html.DisplayFor(modelItem => item.Budget) </td> <td> @Html.DisplayFor(modelItem => item.StartDate) </td> <td> @Html.DisplayFor(modelItem => item.Administrator.FullName) </td> <td> @Html.ActionLink("Edit", "Edit", new { id=item.DepartmentID }) | @Html.ActionLink("Details", "Details", new { id=item.DepartmentID }) | @Html.ActionLink("Delete", "Delete", new { id=item.DepartmentID }) </td> </tr> } </table>
把Create\Edit視圖中 InstructorID
字段標題 改成 Administrator ,把原來一行註釋掉,增長一行:
<div class="form-group"> <label class="control-label col-md-2" for="InstructorID">Administrator</label> @*@Html.LabelFor(model => model.InstructorID, "InstructorID", htmlAttributes: new { @class = "control-label col-md-2" })*@ <div class="col-md-10"> @Html.DropDownList("InstructorID", null, htmlAttributes: new { @class = "form-control" }) @Html.ValidationMessageFor(model => model.InstructorID, "", new { @class = "text-danger" }) </div> </div>
@model EFTest.Models.Department @{ ViewBag.Title = "Delete"; } <h2>Delete</h2> <h3>Are you sure you want to delete this?</h3> <div> <h4>Department</h4> <hr /> <dl class="dl-horizontal"> @*<dt> @Html.DisplayNameFor(model => model.Administrator.LastName) </dt> <dd> @Html.DisplayFor(model => model.Administrator.LastName) </dd>*@ <dt> Administrator </dt> <dd> @Html.DisplayFor(model => model.Administrator.FullName) </dd> <dt> @Html.DisplayNameFor(model => model.Name) </dt> <dd> @Html.DisplayFor(model => model.Name) </dd> <dt> @Html.DisplayNameFor(model => model.Budget) </dt> <dd> @Html.DisplayFor(model => model.Budget) </dd> <dt> @Html.DisplayNameFor(model => model.StartDate) </dt> <dd> @Html.DisplayFor(model => model.StartDate) </dd> </dl> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-actions no-color"> <input type="submit" value="Delete" class="btn btn-default" /> | @Html.ActionLink("Back to List", "Index") </div> } </div>
Delete\Detail如上面修改方法;
效果:
看起來的效果和其餘控制器同樣。。。但這個控制器後臺查詢處理數據都是異步方式。
對於異步方式,有兩點須要注意:
一、異步方式沒法線程安全,換句話說,不要嘗試同一個上下文實例來並行屢次處理;
二、若是你要享受到異步方式的好處,記得全部使用到的而且涉及到數據庫操做的類庫(例如:分頁)都須要採用異步方式;
採用存儲過程來進行增刪改
一些DBA比較推薦使用存儲過程來進行數據操做,之前版本的EF只能經過存儲過程取數據,更新數據作不到,而如今EF6就很簡單能夠實現;
把DAL文件夾中的SchoolContext.cs 中的OnModelCreating方法加入以下一行:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); modelBuilder.Entity<Course>() .HasMany(c => c.Instructors).WithMany(i => i.Courses) .Map(t => t.MapLeftKey("CourseID") .MapRightKey("InstructorID") .ToTable("CourseInstructor")); modelBuilder.Entity<Department>().MapToStoredProcedures(); }
這樣EF就會採用存儲過程進行Department的操做;
首先先要數據庫升級一下,創建好存儲過程;在PMC中輸入 add-migration DepartmentSP
而後在數據庫遷移目錄裏就能夠看到最新的日期時間戳的XXXXXXXXXXXXX_DepartmentSP.sc文件,打開這個文件就能夠看到裏面向數據庫裏增長了3個存儲過程;
在PMC中輸入update-database,執行完的結果,能夠到數據庫裏查看:
有3個存儲過程被產生;
其餘代碼都不用改動,在執行Department增刪改的時候,EF會自動調用這個存儲過程來進行。
如今採用的方式是EF Code First直接定義存儲過程名的方式,若是要使用本身數據庫中已有的存儲過程,則參考:Entity Framework Code First Insert/Update/Delete Stored Procedures.
若是想本身定製存儲過程的產生,能夠在遷移中定義的up方法中來修改。
若是要改變一個已有的之前版本創建的存儲過程,可使用Add-Migration建立一個空的遷移,而後在一個叫AlterStoredProcedure方法中手動寫代碼;