來,給Entity Framework熱熱身


先來看一下Entity Framework緩慢的初始化速度給我們更新程序帶來的一種痛苦。

我們手動更新程序時通常的操作步驟如下:

1)把Web服務器從負載均衡中摘下來

2)更新程序

3)預熱(發出一個請求,完成程序的初始化)

4)把完成更新的Web服務器掛上負載均衡

在預熱階段,我們一般是向首頁(www.cnblogs.com)發出請求(首頁的加載沒有用到Entity Framework)。

如果僅這樣預熱后就將Web服務器上線,將會給部分用戶帶來糟糕的用戶體驗——比如,第1位在發布后推薦博文的用戶將會等待7秒鍾左右(推薦功能中使用了Entity Framework Code First)。

為了避免這樣的糟糕體驗,我們不得不在預熱時發出推薦博文的請求,等EF完成初始化后再發布。這不是一個好的解決方法,因為每個定義的DbContext類型都要進行這個初始化操作。

昨天,我們找到了一個更好的緩解這個問題的方法,在這篇博文中向大家分享一下。

為什么Entity Framework的初始化速度慢如蝸牛呢?

對於在應用程序中定義的每個DbContext類型,在首次使用時,Entity Framework都會根據數據庫中的信息在內存生成一個映射視圖(mapping views),而這個操作非常耗時。

using (var dbcontext = new CnblogsDbContext())
{
    //...
}

比如上面的代碼,在第1次調用CnblogsDbContext進行數據庫操作時會進行緩慢的mapping views生成操作,后續的CnblogsDbContext操作會共享已經生成的mapping views,不受這個問題影響。但是要注意的是你定義的每一個DbContext都會面臨這個問題。

而我們的緩解之道則是在應用程序初始化時一次性觸發所有的DbContext進行mapping views的生成操作——調用StorageMappingItemCollection的GenerateViews()方法。

代碼如下(Entity Framework的版本至少是6.0才支持):

using (var dbcontext = new CnblogsDbContext())
{
    var objectContext = ((IObjectContextAdapter)dbcontext).ObjectContext;
    var mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);
    mappingCollection.GenerateViews(new List<EdmSchemaError>());
}

//對程序中定義的所有DbContext逐一進行這個操作

對於ASP.NET應用程序 ,可以將上面的代碼放在Application_Start或者PreApplicationStartMethod中執行。

我們采用這個方法之后,在程序更新時只需發一個請求讓程序啟動起來,比如訪問首頁(www.cnblogs.com),就可以直接發布。而第1位進行推薦博文操作的用戶,等待時間由原來7秒減少到0.5-0.6秒。

【參考資料】

Pre-Generated Mapping Views 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM