1. 程式人生 > 其它 >探尋ASP.NET MVC鮮為人知的奧祕(2):與Entity Framework配合,讓非同步貫穿始終

探尋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擴充套件方法,增加了非同步載入的功能。

最終呈現效果,擺圖佔地:

這篇就到這裡了,其實這一系列的下一篇還沒確定要寫什麼內容,希望博友基友好朋友們給點意見把。

如果您覺得這篇文章對您有用,勞煩給個贊!

如果您覺得這篇文章可能對別人游泳,勞煩您推薦一個!

如果您覺得這篇文章真扯淡,那麼你又給我刷了個訪問量!