C#無限極分類樹-創建-排序-讀取 用Asp.Net Core+EF實現之方法二:加入緩存機制

来源:http://www.cnblogs.com/xwei/archive/2016/12/15/6184397.html
-Advertisement-
Play Games

在上一篇文章中我用遞歸方法實現了管理菜單,在上一節我也提到要考慮用緩存,也算是學習一下.Net Core的緩存機制。 關於.Net Core的緩存,官方有三種實現: 1.In Memory Caching 我理解是在內容中實現,這種方法適用於單伺服器的生產環境。 2.a Distributed Ca ...


在上一篇文章中我用遞歸方法實現了管理菜單,在上一節我也提到要考慮用緩存,也算是學習一下.Net Core的緩存機制。

關於.Net Core的緩存,官方有三種實現:

1.In Memory Caching 我理解是在內容中實現,這種方法適用於單伺服器的生產環境。

2.a Distributed Cache 分部式緩存實現。

3.Response Cache 這種方式我理解為客戶端緩存。

今天我只用了第一種實現方法,記憶體中緩存,之所以用這種方法我是覺得我這裡用緩存的初衷是為了減少訪問資料庫的次數,而把訪問資料庫頻率最高的數據轉變為對象而放在緩存里。對於分部式說實話目前我也只是聽說和瞭解原理,而沒有做過實現,這裡先不談它。

微軟官方提供的實現In Memory Caching 方法時有一個微軟標準的示例,GitHub地址是  在這裡

示例是用中間件實現的,經過一番學習,用示例裡面提到的方法通過中間件實現了緩存,但怎麼用到Controller里成了一個難題,也可能是我對中間件的瞭解不夠深入吧!反正我是不知道該怎麼辦了!無耐之下,還是仔細研究了一下代碼發現在中間件裡面對緩存的調用(包括設置和取出)其實只在下麵這段代碼里實現:

 1 if(!_memoryCache.TryGetValue(cacheKey, out greeting))
 2             {
 3                 // fetch the value from the source
 4                 greeting = _greetingService.Greet("world");
 5 
 6                 // store in the cache
 7                 _memoryCache.Set(cacheKey, greeting,
 8                     new MemoryCacheEntryOptions()
 9                     .SetAbsoluteExpiration(TimeSpan.FromMinutes(1)));
10                 _logger.LogInformation($"{cacheKey} updated from source.");
11             }
12             else
13             {
14                 _logger.LogInformation($"{cacheKey} retrieved from cache.");
15 }
View Code

也就是 _memoryCache.TryGetValue(cacheKey, out greeting)這一段負責從緩存中取出緩存內容;而_memoryCache.Set(cacheKey, greeting, new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromMinutes(1)));這個方法調用是把數據放到緩存裡面的!

知道了這些以後就著手改造我的程式了:

1.創建IAdminTreeService.cs介面類:

public interface IAdminTreeService
    {
        /// <summary>
        /// 全部節點數據樹
        /// </summary>
        AdminUserTree GetAllTreeData { get; }
    }

2.創建服務AdminTreeServices.cs,用於實現從資料庫中取出管理菜單數據,用服務方式實現這種方式還是借鑒了官方示例的實現方式,這種實現是有其道理的。道理自己琢磨吧,最起碼有得用介面統一。不再啰嗦直接代碼:

  1  public class AdminTreeServices:IAdminTreeService
  2     {
  3         /// <summary>
  4         /// EF數據訪問配置
  5         /// </summary>
  6         private readonly ApplicationDbContext _basecontext;
  7 
  8         public AdminTreeServices(ApplicationDbContext context)
  9         {
 10             _basecontext = context;            
 11         }
 12 
 13         /// <summary>
 14         /// 建立無限極節點樹-管理菜單
 15         /// </summary>
 16         /// <returns></returns>
 17         public AdminUserTree GetAllTreeData
 18         {
 19             get
 20             {
 21                 AdminUserTree result = new AdminUserTree();
 22                 //初始化一個節點做為根節點
 23                 result.NodeID = 0;
 24                 result.Text = "管理員菜單";
 25                 result.Url = "";
 26                 result.ParentID = -1;
 27                 result.Location = "";
 28                 result.OrderID = 0;
 29                 result.Comment = "來源為資料庫";
 30                 result.ImageUrl = "";
 31                 result.PermissionID = 0;
 32                 result.Level = 0;
 33                 result.ChildNumberl = 0;
 34                 //把根節點傳遞給遞歸方法去創建子節點
 35                 result.ChildNode = BuildMenuTree(result, -1);
 36                 return result;
 37 
 38             }
 39            
 40         }
 41         
 42 
 43         /// <summary>
 44         /// 遞歸創建子節點方法
 45         /// </summary>
 46         /// <param name="node">要為其分配子節點的父級節點</param>
 47         /// <param name="levelID">層級關係</param>
 48         /// <returns></returns>
 49         protected List<AdminUserTree> BuildMenuTree(AdminUserTree node, int levelID)
 50         {
 51             var listtree = _basecontext.Admintree;
 52 
 53             //從資料庫中取出node節點的全部子節點 條件:m.ParentID==node.NodeID
 54             List<AdminUserTree> lt = listtree.Where(m => m.ParentID == node.NodeID)
 55                                             .Select(m => new AdminUserTree()
 56                                             {
 57                                                 NodeID = m.NodeID
 58                                             ,
 59                                                 Text = m.Text
 60                                             ,
 61                                                 Url = m.Url
 62                                             ,
 63                                                 ParentID = m.ParentID
 64                                             ,
 65                                                 Location = m.Location
 66                                             ,
 67                                                 OrderID = m.OrderID
 68                                             ,
 69                                                 Comment = m.Comment
 70                                             ,
 71                                                 ImageUrl = m.ImageUrl
 72                                             ,
 73                                                 PermissionID = m.PermissionID
 74                                             })
 75                                             .ToList();
 76 
 77             if (lt != null)
 78             {
 79                 //節點深度
 80                 node.Level = levelID + 1;
 81                 //子節點數量,便於前端遞歸輸出時調用
 82                 node.ChildNumberl = lt.Count;
 83                 for (int i = 0; i < lt.Count; i++)
 84                 {
 85                     //遞歸調用創建子節點
 86                     lt[i].ChildNode = BuildMenuTree(lt[i], node.Level);
 87                 }
 88                 return lt;
 89 
 90             }
 91             else
 92             {
 93                 return null;
 94             }
 95 
 96 
 97 
 98 
 99         }
100 
101     }
AdminTreeServices

3.管理頁面基類 AdminBase.cs:

 1 public class AdminBase: Controller
 2     {
 3         /// <summary>
 4         /// EF數據訪問配置
 5         /// </summary>
 6         private readonly ApplicationDbContext _basecontext;        
 7         private readonly IAdminTreeService _adminTreeService;
 8         private readonly ILogger<AdminUserTree> _logger;
 9         private readonly IMemoryCache _memoryCache;
10 
11 
12         /// <summary>
13         /// 管理菜單 這裡是基數,聲明為屬性以便控制器裡面可以用到
14         /// </summary>
15         public AdminUserTree leftMenu { get; set; }
16 
17 
18         public AdminBase(ApplicationDbContext context,
19                             IMemoryCache memoryCache, 
20                             ILogger<AdminUserTree> logger, 
21                             IAdminTreeService adminTreeService)
22         {
23             _basecontext = context;
24             //初始化無限極分類管理菜單
25             _logger = logger;
26             _adminTreeService = adminTreeService;
27             _memoryCache = memoryCache;
28             leftMenu = GetAdminTreeByCache();
29         }
30 
31         /// <summary>
32         /// 從緩存中讀取節點樹
33         /// </summary>
34         /// <param name="httpContext"></param>
35         /// <returns></returns>
36         public AdminUserTree GetAdminTreeByCache()
37         {
38             string cacheKey = "AdminTree-Base";
39             AdminUserTree adminTree;
40 
41             //獲取緩存內容的一種方式
42             // greeting = _memoryCache.Get(cacheKey) as string;
43             
44             //另一種獲取緩存內容的方式,
45            // alternately, TryGet returns true if the cache entry was found
46             if (!_memoryCache.TryGetValue(cacheKey, out adminTree))
47             {
48                 //緩存中不存在該內容,從數據介面中通過訪問資料庫獲取。
49                 adminTree = _adminTreeService.GetAllTreeData;
50 
51                 // 絕對過期時間方法,在設置緩存時3分鐘後過期
52                 //_memoryCache.Set(cacheKey, adminTree,
53                 //    new MemoryCacheEntryOptions()
54                 //    .SetAbsoluteExpiration(TimeSpan.FromMinutes(3)));
55                 //相對過期時間方法,相對於最後一次調用後3分鐘過期
56                 _memoryCache.Set(cacheKey, adminTree,
57                     new MemoryCacheEntryOptions()
58                     .SetSlidingExpiration(TimeSpan.FromMinutes(3)));
59                 //記錄日誌
60                 _logger.LogInformation($"{cacheKey} From Data."+DateTime.Now.AddMinutes(3).ToString());
61             }
62             else
63             {
64                 //記錄日誌,這裡表示當前數據是從緩存中讀取的。
65                 _logger.LogInformation($"{cacheKey} From Cacha."+DateTime.Now.ToString());
66             }
67 
68             return adminTree;
69 
70         }
71 }
AdminBase

4.最後不要忘記了在Startup.cs中加入以下代碼 :

1 public void ConfigureServices(IServiceCollection services)
2         {
3             …………
4              services.AddMemoryCache();
5 
6              services.AddTransient<IAdminTreeService, AdminTreeServices>();
7

 

 

在這裡基本就實現了通過緩存讀取數據了!至於Controller中的實現沒有變化請參考我的上篇隨筆:

C#無限極分類樹-創建-排序-讀取 用Asp.Net Core+EF實現

為了方便閱讀這裡再放一遍菜單節點類代碼:

 1 /// <summary>
 2     /// 無限極節點類
 3     /// </summary>
 4     public class AdminUserTree
 5     {
 6         /// <summary>
 7         /// 節點信息
 8         /// </summary>
 9         public int NodeID { get; set; }
10         /// <summary>
11         /// 節點名稱
12         /// </summary>
13         public string Text { get; set; }
14         /// <summary>
15         /// 父節點ID
16         /// </summary>
17         public int ParentID { get; set; }
18         /// <summary>
19         /// 對應的鏈接地址
20         /// </summary>
21         public string Url { get; set; }
22         public int? PermissionID { get; set; }
23         public int? OrderID { get; set; }
24         public string Location { get; set; }
25         public string Comment { get; set; }
26         public string ImageUrl { get; set; }
27         /// <summary>
28         /// 層級
29         /// </summary>
30         public int Level { get; set; }
31         /// <summary>
32         /// 子節點數目(很重要)
33         /// </summary>
34         public int ChildNumberl { get; set; }
35 
36         /// <summary>
37         ///  子節點 (子節點是一個List)這種用法叫什麼?
38         /// </summary>
39         public List<AdminUserTree> ChildNode { get; set; }
40     }
View Code

最後把運行時日誌截圖放出來:

首次訪問:

上面有很多的資料庫訪問語句,日誌提示數據來源與資料庫

再次訪問:

這裡就是直接從緩存中讀取出來的內容了!

好了今天的內容就寫到這裡。

按照先前的計劃,下一步該研究一下用戶及許可權的內容了,這次我打算研究一下 ASP.NET Identity 身份驗證和基於角色的授權,網上有很多相關的資料了,可我還是沒有看明白怎麼和我實際的項目相結合。估計要花幾天時間了!

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...