91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

改善 ASP.NET MVC 代碼庫的 5 點建議

發布時間:2020-06-13 23:08:14 來源:網絡 閱讀:263 作者:OneAPM123 欄目:編程語言
MVC,建議

剛剛檢查完支持工單中的一些代碼,筆者想針對 ASP.NET MVC 應用的改進寫一些建議。這些內容仍在筆者腦海中,愿與各位一同分享。若你已使用 MVC 一段時間,那么以下內容可能并不新鮮。本文更適用于不常使用 MVC 或尚未充分了解 MVC 的讀者。

假設以下場景:你想弄清楚一個網絡應用在生產環境下為何消耗了 Web 服務器2GB 內存,于是,你將生產環境中運行的應用版本部署到本地運行,用于分析和調試。

仔細查看代碼后,你認真地分析,可能還時不時搖搖頭,最終弄清了問題的本質,那么此時,你應該給出反饋了。

這就是筆者今天的經歷,從中總結出5點建議,希望能使讀者在使用 ASP.NET MVC 代碼時更加得心應手。

1、了解問題范疇內的查詢

筆者收到的支持工單,其根本原因在于,從數據庫中提取了大量數據,導致占用了過量內存。

這一問題十分常見。假如你建立了一個普通的博客,其中包含了文章以及多種媒體(圖片、視頻、附件)。你將一個 Media 數組放到 Post 域對象中,后者將所有圖片數據儲存在一個字節數組中。由于你使用了 ORM,因此需要采用某種方法將域模型設計完善;我們都經歷過這一步。

public class BlogPost {
  public ICollection<BlogMedia> Media { get; set; }
}
public class BlogMedia {
  public byte[] Data { get; set; }
  public string Name { get; set; }
}


這種設計并沒有大的不妥,你很準確地建立了域模型。但問題在于,當你通過最常用的 ORM 發起查詢時,所有與博客文章相關的數據都會被加載出來。

public IList<BlogPost> GetNewestPosts(int take) {
  return _db.BlogPosts.OrderByDescending(p => p.PostDate).Take(take).ToList();
}

這一行看起來毫無問題(除非你曾受其困擾,所以了解它并非無害),但如果不取消延遲加載或沒讓 ORM 忽略日志媒體上的大「Data」屬性,那么就可能導致非常嚴重的后果。

你應當了解 ORM 是如何進行查詢和映射對象的,并確保所查詢內容就是需要的內容(比如使用 projection),這一點十分重要。

public IList<PostSummary> GetNewestPosts(int take) {
  return _db.BlogPosts.OrderByDescending(p => p.PostDate).Take(take).Select(p => new PostSummary() {
      Title = p.Title,
      Id = p.Id
  }).ToList();
}

這能確保只抓取任務真正需要的數據量。如果你要做的僅僅是使用標題和 ID 在主頁上建立一個鏈接,那么得到這倆屬性就夠了

你可以在知識庫中準備5種以上的方法,為使用戶界面更加完善,再仔細也不為過。

2、不要從視圖中調用知識庫

這一條比較難注意到。設想 MVC 視圖中的以下代碼:

@foreach(var post in Model.RelatedPosts) {
  ...
}

看起來沒什么問題,但如果仔細看看這一模型屬性中隱含的內容呢?

public class MyViewModel {
  public IList<BlogPost> RelatedPosts {
      get { return new BlogRepository().GetRelatedPosts(this.Tags); }
  }
}

呀!「視圖模型」中含有業務邏輯,此外還直接調用了一個數據存取方法。如此一來,數據存取代碼被引入了陌生的區域,并隱藏在屬性中。將此代碼移動到控制器中,便于對其進行討論并有意識地為視圖模型添加內容。

此處正好說明一下,適當的單元測試可幫助發現此類問題;由于肯定不能攔截對這此類方法的調用,你可能會恍然大悟,不該將知識庫注入視圖模型中。

3、充分利用局部模塊和子動作

如需在視圖中執行業務邏輯,那就應重新考慮視圖模型和邏輯。不建議在 MVC Razor 視圖中執行此類操作。

@{
  var blogController = new BlogController();
}
<ul>
@foreach(var tag in blogController.GetTagsForPost(p.Id)) {
  <li>@tag.Name</li>
}
</ul>

切勿在視圖中使用業務邏輯,但除此之外,你可以創建一個控制器!將業務邏輯移動到動作方法中,并將視圖模型用于原本的用途。還可以將業務邏輯移動到單獨的動作方法中,這一動作方法僅在視圖內被調用,這樣就可在必要時單獨對其進行緩存。

//In the controller:
[ChildActionOnly]
[OutputCache(Duration=2000)]
public ActionResult TagsForPost(int postId) {
  return View();
}
//In the view:
@{Html.RenderAction("TagsForPost", new { postId = p.Id });}

注意 「ChildActionOnly」 屬性。MSDN中提到:

任何一個標有 「ChildActionOnlyAttribute」的方法都只能與 「Action」或「RenderAction」HTML 擴展方法一同被調用。

這就意味著,沒有人能通過操作 URL 來訪問你的子動作(如果你采用了默認路徑)。

在 MVC 庫中,局部模塊和子動作都是很有用的工具,所以充分利用起來吧!

4、緩存重要的東西

有了以上的代碼做鋪墊,如果只緩存視圖模型,又會有怎樣的效果呢?

public ActionResult Index() {
  var homepageViewModel = HttpContext.Current.Cache["homepageModel"] as HomepageViewModel;
  if (homepageViewModel == null) {
      homepageViewModel = new HomepageViewModel();
      homepageViewModel.RecentPosts = _blogRepository.GetNewestPosts(5);
      HttpContext.Current.Cache.Add("homepageModel", homepageViewModel, ...);
  }
  return View(homepageViewModel);
}

什么效果也沒有!由于是通過視圖中的控制器變量和視圖模型中的屬性進入數據層,因此并不能提升性能……緩存視圖模型并沒有什么用處。

試試緩存 MVC 動作的輸出吧:

[OutputCache(Duration=2000)]
public ActionResult Index() {
  var homepageViewModel = new HomepageViewModel();
  homepageViewModel.RecentPosts = _blogRepository.GetNewestPosts(5);
  return View(homepageViewModel);
}

請注意非常好用的「OutputCache」屬性。MVC 支持 ASP.NET 輸出緩存,因此請在適當情況下,充分利用這一特點。如需緩存模型,那么模型基本上應為帶自動(且只讀)屬性的 POCO,不能調用其他知識庫方法。

另外還想介紹筆者尚未嘗試的一個好方法,即采用不同的輸出緩存供應商,從而在AppFabric、NoSQL 或其他任何需要的地方進行緩存。MVC 的可擴展性非常強。

5、大膽使用 ORM

如果不好好利用 ORM 的特征集,那真是極大的損失。筆者所檢查的代碼庫中用到了 NHibernate,但是并未真正利用好。本可以用來解決一部分內存問題的 NHibernate高級射影功能完全被忽略了。這一問題有時是因為使用“庫模式”所造成的僵化思維,有時則是由于缺乏必要的知識。

與僅僅使用基本的類方法相比,通過利用 EF 或 NHibernate 特征,知識庫的功能可以大大增加。它們可以在控制器中形成和返回你真正想要的數據,大大增強控制器的邏輯性。趕緊閱讀 ORM 文件,了解一下它可以提供的功能吧,這將使你受益良多。

筆者認為,采用知識庫模式,就好比驅除掉霧霾,使明媚的陽光從 ORM 窗口照進來。剛接觸 RavenDB 時,筆者丟棄了知識庫層(實際上是整個數據項目),在應用服務層中完全使用 Raven 查詢,用了一點點擴展方法來重復使用查詢邏輯。筆者發現,許多邏輯都明顯依賴于特定的上下文,且利用 Raven 的擴展特性進行投射、形成并分批處理查詢,大有益處。

那只是你一家之言……

如果你認為可以將 ORM 抽象化,筆者強烈建議你換個角度思考。ORM 確實是抽象概念,如果你認為,由于 ORM 是「抽象」的,所以輕而易舉就能用別的 ORM 置換現有的 ORM,那么事實會讓你大吃一驚。因為我之前也是這么想的,直到我了解到,轉換至 Raven 簡直改變了我整個代碼庫,這是我完全沒有預料到的。ORM 不僅僅影響到數據存取,還會影響域以及業務邏輯,甚至會影響用戶界面。通過移除知識庫抽象,可以切實降低數據存取代碼的整體復雜度

「常識并非人人皆知」

家父常常拿這句話提醒我。有時候,通過仔細查閱代碼,也會發現你認為人人皆知的道理,事實并非如此;你可能從實踐經驗中了解到這一點,或在 google 上讀到這一點,就錯誤地假設這是人人都知道的事實了。

希望這篇文章能幫到需要的人!

OneAPM 助您輕松鎖定 .NET 應用性能瓶頸,通過強大的 Trace 記錄逐層分析,直至鎖定行級問題代碼。以用戶角度展示系統響應速度,以地域和瀏覽器維度統計用戶使用情況。想閱讀更多技術文章,請訪問 OneAPM 官方博客。

本文轉自 OneAPM 官方博客

原文地址:http://kamranicus.com/blog/2014/01/29/5-tips-to-improve-your-mvc-site/


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

辰溪县| 鄯善县| 乌兰浩特市| 富宁县| 东乌珠穆沁旗| 平邑县| 阳春市| 礼泉县| 龙山县| 武夷山市| 汾西县| 阆中市| 东港市| 清镇市| 辉南县| 沂源县| 临武县| 英超| 蛟河市| 天门市| 格尔木市| 夏津县| 洛宁县| 玉环县| 临沭县| 尚志市| 林口县| 芷江| 清涧县| 中卫市| 潮州市| 凌海市| 军事| 新邵县| 长子县| 彭山县| 响水县| 凤山市| 福鼎市| 永登县| 利津县|