探尋ASP.NET MVC鮮為人知的奧祕(2):與Entity Framework配合,讓非同步貫穿始終
Why
在應用程式,尤其是網際網路應用程式中,效能一直是很多大型網站的困擾,由於Web2.0時代的到來,人們更多的把應用程式從C/S結構遷移到B/S結構,這樣會帶來客戶端輕量,部署、試試方便快捷等優勢,但是萬事萬物都有他的兩面性,這樣的發展趨勢同時也帶來了其他方便的不好影響,其中很重要的一項就是系統對伺服器的效能要求提高,隨著使用者量增多和系統功能的增加,伺服器效能漸漸成了短板。
這種效能的影響,可以從諸多方面進行優化,比如使用負載均衡的伺服器,建立伺服器叢集等方式,但是這是從硬體配置方面的優化,而在軟體開發方面,同樣也可以做很多效能方面的優化。
我們都知道,微軟的IIS伺服器中每個執行緒數量是有限的,在以往的ASP.NET MVC應用程式中,當一個請求到達伺服器,IIS從執行緒池中建立一個執行緒開始執行呼叫,當執行完所有的操作將請求返回,再釋放執行緒,也就是說整個呼叫過程中,執行緒是一隻持有的。
可如果程式訪問人數增加,執行緒就成了一種稀缺的資源,如果在一次請求中,需要訪問遠端資料庫、或者進行大的IO處理,這是請求很可能就會長期的持有一個執行緒,而當用戶量大這種長期請求多的時候,執行緒池就會迅速的被佔滿,請求進入等待佇列,而且等待佇列也是有最大長度的,同時還可能將請求超時返回給瀏覽器端。
所以,我們就會想需要一種非同步的方式來執行請求,當遇到長請求的時候,將請求從IIS執行緒交由後臺執行緒處理,釋放當前執行緒,處理完成後,再從執行緒池中選擇執行緒繼續進行請求的其它處理。
How
在ASP.NET MVC3種,已經提供了AsyncController,可以建立非同步的控制器,可那時候需要用到Async和Completed方法對的模式來處理,而現在,我們不需要單獨去實現繼承自AsyncController的類,只需要在原有Action方法上加上特定的關鍵字和返回型別,就可以建立非同步的控制器。
而且,在Entity Framework6中,同樣實現了對資料的非同步查詢和儲存的功能,這就使得我們在應用程式整個過程中,都可以以非同步的方式處理邏輯。
Let’s do it
示例使用VS2013建立一個ASP.NET MVC5專案”AsyncExample“(不糾結於設計原則,注意重點)
在Models資料夾中新增一個使用者類:
namespace AsyncExample.Models { public class User { [Key] public int Id { get; set; } public string IdentityToken { get; set; } public string Name { get; set; } } }
給專案新增Entity Framework的引用
PM> install-package entityframework
建立DbContext子類AsyncDbContext類:
namespace AsyncExample.Models
{
public class AsyncDbContext:DbContext
{
public DbSet<User> Users { get; set; }
public AsyncDbContext()
: base("name=DefaultConnection")
{
}
}
}
更新Web.config,新增資料庫連線串。
開啟Entity framework的Migrations功能:
PM> enable-migrations
BTW:在新版本的Entity Framework中,已經可以使用自動遷移,不需要為每一次的模型變更手動的去升級資料庫結構,開啟的方法很簡單:
開啟Migrations資料夾下的Configuration.cs檔案,在Configuration預設建構函式中可以看到一個AutomaticMigrationsEnabled屬性被設定為False,改成True就可以自動遷移了,顫抖吧
資料庫更新完之後,來建立一個控制器:
using System.Data.Entity;
namespace AsyncExample.Controllers
{
public class UserController : Controller
{
AsyncDbContext context = new AsyncDbContext();
public ActionResult Create()
{
return View();
}
[HttpPost]
public async Task<ActionResult> Create(User user)
{
context.Users.Add(user);
await context.SaveChangesAsync();
return RedirectToAction("List");
}
public async Task<ActionResult> List()
{
return View(await context.Users.ToListAsync());
}
}
}
可以看到在Create和List兩個方法中,都使用了async和aswait建立了兩個非同步的方法,我們也只直接繼承了Controller,因為現在的同步非同步的功能都放在了這個類裡,同時我們需要引入Systen.Data.Entity這個名稱空間,其中包含了對IQueryable型別的ToListAsync擴充套件方法,增加了非同步載入的功能。
最終呈現效果,擺圖佔地:
這篇就到這裡了,其實這一系列的下一篇還沒確定要寫什麼內容,希望博友基友好朋友們給點意見把。
如果您覺得這篇文章對您有用,勞煩給個贊!
如果您覺得這篇文章可能對別人游泳,勞煩您推薦一個!
如果您覺得這篇文章真扯淡,那麼你又給我刷了個訪問量!