项目架构开发:数据访问层之Cache
数据访问层简单介绍
数据访问层,提供整个项目的数据访问与持久化功能。在分层系统中所有有关数据访问、检索、持久化的任务,最终都将在这一层完成。
来看一个比较经典的数据访问层结构图

大概可以看出如下信息
1、有缓存、日志、异常处理、数据CRUD、查询及数据事务等功能
2、无缝对接如EF、ADO.NET、NH、Dapper等数据访问技术
3、对外只开放接口层,隐藏具体实现,这样就可以解耦业务层与数据访问层
今天斗胆通过一个简单实例来实践一下,如有不妥的地方,欢迎指正
创建接口层,定义可以提供的一些服务接口

这里我们一个有5种服务接口,方法的功能就不介绍了,应该都能看懂
缓存接口:ICache.cs
public interface ICache<T> where T : class
{
IEnumerable<T> Gets(string key);
T Get(string key);
bool Sets(string key, IEnumerable<T> value, TimeSpan expiresIn);
bool Set(string key, T value, TimeSpan expiresIn);
bool Remove(string key);
}
缓存服务的实现
因为可能支持多种缓存,所以我实现了Web缓存与Redis缓存,这2中缓存分别在项目初期和后期集群中可能会用到

我们来看HttpRuntimeCache.cs (还有一种Web缓存HttpContext.Cache,不够这种只能在Web应用使用,所以一般不推荐)
public class HttpRuntimeCache<T> : ICache<T> where T : class
{
public HttpRuntimeCache()
{ } public T Get(string key)
{
if (System.Web.HttpRuntime.Cache[key] == null)
{
return default(T);
} return System.Web.HttpRuntime.Cache[key] as T;
} public bool Set(string key, T value, TimeSpan expiresIn)
{
Set(key, value, expiresIn.Seconds);
return true;
} public bool Remove(string key)
{
System.Web.HttpRuntime.Cache.Remove(key);
return true;
} private void Set(string key, object value, int absoluteSeconds)
{
System.Web.HttpRuntime.Cache.Insert(key, value, null, DateTime.Now.AddSeconds(absoluteSeconds), TimeSpan.FromSeconds());
}
}
现在缓存功能已经实现了;大家应该很容易想到怎麼使用了,比如在业务层这样使用
ICache<User> cache = new HttpRuntimeCache<User>();
var user = cache.Get("key");
其实这样是不对的,因为这样的话接口ICache相当于没什么用处,没有起到应有的作用(隔离具体实现)
如果要换另一种缓存实现(比如redis),那还要在所有使用了 new HttpRuntimeCache<User>() 的地方改正过来
这样的耦合要去掉;有2种方式,通过IOC在实例化的时候依赖注入;另一种就是新建一个基础设施层,业务层依赖于这一层
因为业务层肯定是需要调用一些Utilities、Helper等类型的工具类,这个应该是躲不掉的,再怎么接口隔离也去除不了这点
基础设施层的实现

Cache.cs
public sealed class Cache<T> where T : class
{
private readonly static ICache<T> cacheProvider; static Cache()
{
cacheProvider = ProviderHelper<T>.GetCacheProvider();
} public static IEnumerable<T> Gets(string key)
{
return cacheProvider.Gets(key);
} public static T Get(string key)
{
return cacheProvider.Get(key);
} public static bool Sets(string key, IEnumerable<T> value, TimeSpan expiresIn)
{
return cacheProvider.Sets(key, value, expiresIn);
} public static bool Set(string key, T value, TimeSpan expiresIn)
{
return cacheProvider.Set(key, value, expiresIn);
} public static bool Remove(string key)
{
return cacheProvider.Remove(key);
}
}
ProviderHelper.cs 实现如下图

至此,缓存功能实现完毕,我们新建一个测试项目看看结果

[TestClass]
public class CacheTest
{
[TestMethod]
public void Set()
{
var user = new LoginUser()
{
Id = Guid.NewGuid(),
LoginName = "LoginName",
IsEnabled = ,
Password = "mima1987",
CreateTime = DateTime.Now
}; Cache<LoginUser>.Set("UnitTest3.TestMethod1", user, TimeSpan.FromSeconds());
var user2 = Cache<LoginUser>.Get("UnitTest3.TestMethod1"); Assert.AreEqual(user.Id, user2.Id);
}
}

看来没有什么问题。
项目架构开发系列
- 项目架构开发:数据访问层之Cache
- 项目架构开发:数据访问层之Logger
- 项目架构开发:数据访问层之Repository
- 项目架构开发:数据访问层之Query
- 项目架构开发:数据访问层之UnitOfWork
项目架构开发:数据访问层之Cache的更多相关文章
- 企业级应用架构(三)三层架构之数据访问层的改进以及测试DOM的发布
在上一篇我们在宏观概要上对DAL层进行了封装与抽象.我们的目的主要有两个:第一,解除BLL层对DAL层的依赖,这一点我们通过定义接口做到了:第二,使我们的DAL层能够支持一切数据访问技术,如Ado.n ...
- 项目架构开发:数据访问层之Logger
接上文 项目架构开发:数据访问层之Cache 本章我们继续ILogger的开发 ILogger.cs public interface ILogger { void Info(object messa ...
- 项目架构开发:数据访问层之Repository
接上文 项目架构开发:数据访问层之Logger 本章我们继续IRepository开发,这个仓储与领域模式里边的仓储有区别,更像一个工具类,也就是有些园友说的“伪仓储”, 这个仓储只实现单表的CURD ...
- 项目架构开发:数据访问层之UnitOfWork
接上文 项目架构开发:数据访问层之IQuery 本章我们继续IUnitOfWork的开发,从之前的IRepository接口中就可以看出,我们并没有处理单元事务, 数据CUD每次都是立即执行的,这样有 ...
- 项目架构开发:数据访问层之Query
接上文 项目架构开发:数据访问层之Repository 上一章我们讲了IRepository接口,这张我们来讲IQuery 根据字面意思就可以知道,这次主要讲数据查询,上一章我们只针对单表做了查询的操 ...
- 随机获得MySQL数据库中100条数据方法 驾照题库项目 MVC架构 biz业务层的实现类 根据考试类型rand或order通过dao数据访问层接口得到数据库中100或全部数据
package com.swift.jztk.biz; import java.util.Collections; import java.util.Comparator; import java.u ...
- 数据访问层之Repository
数据访问层之Repository 接上文 项目架构开发:数据访问层之Logger 本章我们继续IRepository开发,这个仓储与领域模式里边的仓储有区别,更像一个工具类,也就是有些园友说的“伪 ...
- asp.net/wingtip/创建数据访问层
一. 什么是数据访问层 在wingtip项目中,数据访问层是对以下三者的总称:1. product类等数据相关的实体类(class)2. 数据库(database),对实体类成员的存储3. 上述二者的 ...
- servlet层调用biz业务层出现浏览器 500错误,解决方法 dao数据访问层 数据库Util工具类都可能出错 通过新建一个测试类复制代码逐步测试查找出最终出错原因
package com.swift.jztk.servlet; import java.io.IOException; import javax.servlet.ServletException; i ...
随机推荐
- Sublime Text3 使用手册
1.标签页切换:ctrl+tab 2.Sublime Text3的配色方案(Preferences——配色方案)我选白色方案是:Eiffel;深色方案我选:Monokai 3.左边资源栏:先ctrl+ ...
- OS X EI Capitan 10.11 & xcode 7.0 beta(7A120f) -- cocoapods安装失败
1.sudo gem install cocoapods: ERROR:While executing gem ... (Errno:EPERM) Operation not permitted - ...
- MySQL连接数据库报时区错误:java.sql.SQLException: The server time zone value
连接MySQL数据库时报以下时区错误信息: java.sql.SQLException: The server time zone value '�й���ʱ��' is unrecognized ...
- Delphi 常用API 函数
Delphi 常用API 函数 AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小 AnyPopup 判断屏幕上是否存在任何弹出式窗口 ArrangeIconic ...
- HDU1848-Fibonacci again and again
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1848 这个题目代码不是很复杂,但那个等价类,(SG函数)没怎么理解, 题目难,不过代码不怎么复杂,在网 ...
- Eclipse中应用的调试
作为编程人员,程序的调试是一项基本功.在不使用IDE的时候,程序的调试多数是通过日志或者输入语句(System.out.println)的方式.可以把程序运行的轨迹或者程序运行过程中的状态显示给用户, ...
- PHP中目录解析函数
dirname(string path):给出一个包含有指向一个文件的全路径的字符串,本函数返回去掉文件名后的目录名. 斜线(/)和反斜线(\)都可以用作目录分隔符.在其它环境下是斜线(/). dir ...
- 在JS中使用COM组件的方法
首先创建一个COM组件,插入一个双接口Itest,在此接口上实现以下三个方法: STDMETHODIMP Ctest::test(void) //无输入输出参数 { // TODO: 在此添加实现代码 ...
- Bootstrap相关的网站
http://www.bootcss.com/ http://expo.bootcss.com/ http://www.webresourcesdepot.com/20-beautiful-resou ...
- Git学习之路(2)-安装GIt和创建版本库
▓▓▓▓▓▓ 大致介绍 前面一片博客介绍了Git到底是什么东西,如果有不明白的可以移步 Git学习之路(1)-Git简介 ,这篇博客主要讲解在Windows上安装Git和创建一个版本库 ▓▓▓▓▓▓ ...