項目架構開發:數據訪問層之Cache


數據訪問層簡單介紹

數據訪問層,提供整個項目的數據訪問與持久化功能。在分層系統中所有有關數據訪問、檢索、持久化的任務,最終都將在這一層完成。

來看一個比較經典的數據訪問層結構圖

大概可以看出如下信息

1、有緩存、日志、異常處理、數據CRUD、查詢及數據事務等功能

2、無縫對接如EF、ADO.NET、NH、Dapper等數據訪問技術

3、對外只開放接口層,隱藏具體實現,這樣就可以解耦業務層與數據訪問層

 

今天斗膽通過一個簡單實例來實踐一下,如有不妥的地方,歡迎指正

創建接口層,定義可以提供的一些服務接口

 

這里我們一個有5種服務接口,方法的功能就不介紹了,應該都能看懂

緩存接口:ICache.cs

1     public interface ICache<T> where T : class
2     {
3         IEnumerable<T> Gets(string key);
4         T Get(string key);
5         bool Sets(string key, IEnumerable<T> value, TimeSpan expiresIn);
6         bool Set(string key, T value, TimeSpan expiresIn);
7         bool Remove(string key);
8     }

 

緩存服務的實現

因為可能支持多種緩存,所以我實現了Web緩存與Redis緩存,這2中緩存分別在項目初期和后期集群中可能會用到

 

我們來看HttpRuntimeCache.cs (還有一種Web緩存HttpContext.Cache,不夠這種只能在Web應用使用,所以一般不推薦)

 1 public class HttpRuntimeCache<T> : ICache<T> where T : class
 2     {
 3         public HttpRuntimeCache()
 4         {
 5 
 6         }
 7 
 8         public T Get(string key)
 9         {
10             if (System.Web.HttpRuntime.Cache[key] == null)
11             {
12                 return default(T);
13             }
14 
15             return System.Web.HttpRuntime.Cache[key] as T;
16         }
17 
18         public bool Set(string key, T value, TimeSpan expiresIn)
19         {
20             Set(key, value, expiresIn.Seconds);
21             return true;
22         }
23 
24         public bool Remove(string key)
25         {
26             System.Web.HttpRuntime.Cache.Remove(key);
27             return true;
28         }
29 
30         private void Set(string key, object value, int absoluteSeconds)
31         {
32             System.Web.HttpRuntime.Cache.Insert(key, value, null, DateTime.Now.AddSeconds(absoluteSeconds), TimeSpan.FromSeconds(0));
33         }
34     }

 

現在緩存功能已經實現了;大家應該很容易想到怎麼使用了,比如在業務層這樣使用

1 ICache<User>  cache = new HttpRuntimeCache<User>();
2 var user = cache.Get("key");

 

其實這樣是不對的,因為這樣的話接口ICache相當於沒什么用處,沒有起到應有的作用(隔離具體實現)

如果要換另一種緩存實現(比如redis),那還要在所有使用了 new HttpRuntimeCache<User>() 的地方改正過來

這樣的耦合要去掉;有2種方式,通過IOC在實例化的時候依賴注入;另一種就是新建一個基礎設施層,業務層依賴於這一層

因為業務層肯定是需要調用一些Utilities、Helper等類型的工具類,這個應該是躲不掉的,再怎么接口隔離也去除不了這點

 

基礎設施層的實現

 

Cache.cs 

 1     public sealed class Cache<T> where T : class
 2     {
 3         private readonly static ICache<T> cacheProvider;
 4 
 5         static Cache()
 6         {
 7             cacheProvider = ProviderHelper<T>.GetCacheProvider();
 8         }
 9 
10         public static IEnumerable<T> Gets(string key)
11         {
12             return cacheProvider.Gets(key);
13         }
14 
15         public static T Get(string key)
16         {
17             return cacheProvider.Get(key);
18         }
19 
20         public static bool Sets(string key, IEnumerable<T> value, TimeSpan expiresIn)
21         {
22             return cacheProvider.Sets(key, value, expiresIn);
23         }
24 
25         public static bool Set(string key, T value, TimeSpan expiresIn)
26         {
27             return cacheProvider.Set(key, value, expiresIn);
28         }
29 
30         public static bool Remove(string key)
31         {
32             return cacheProvider.Remove(key);
33         }
34     }

 

 ProviderHelper.cs 實現如下圖

 

至此,緩存功能實現完畢,我們新建一個測試項目看看結果

 1     [TestClass]
 2     public class CacheTest
 3     {
 4         [TestMethod]
 5         public void Set()
 6         {
 7             var user = new LoginUser()
 8             {
 9                 Id = Guid.NewGuid(), 
10                 LoginName = "LoginName",
11                 IsEnabled = 1,
12                 Password = "mima1987",
13                 CreateTime = DateTime.Now
14             };
15 
16             Cache<LoginUser>.Set("UnitTest3.TestMethod1", user, TimeSpan.FromSeconds(10));
17             var user2 = Cache<LoginUser>.Get("UnitTest3.TestMethod1");
18 
19             Assert.AreEqual(user.Id, user2.Id);
20         }
21     }

 

看來沒有什么問題。

 

項目架構開發系列

 


免責聲明!

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



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