项目架构开发:数据访问层之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 ...
随机推荐
- JS内存泄漏排查方法——Chrome Profiles
一.概述 Google Chrome浏览器提供了非常强大的JS调试工具,Heap Profiling便是其中一个.Heap Profiling可以记录当前的堆内存(heap)快照,并生成对象的描述文件 ...
- Python3基础 global关键字 使函数的局部变量升格为全局变量
镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...
- Java元注解
元注解是指注解的注解,包括@Retention @Target @Document @Inherited四种. 1.@Retention: 定义注解的保留策略@Retention(RetentionP ...
- HTML5 + AJAX ( 原生JavaScript ) 异步多文件上传
这是在上篇 HTML5 + AJAX ( jQuery版本 ) 文件上传带进度条 的修改版本.后台代码不变就可以接着使用,但是脚本不再使用jQuery了,改为原生的 JavaScript 代码,所以我 ...
- 解剖 Elasticsearch 集群 - 之三
解剖 Elasticsearch 集群 - 之三 本篇文章是一系列涵盖 Elasticsearch 底层架构和原型示例的其中一篇.在本篇文章中,我们会讨论 Elasticsearch 如何提供准实时搜 ...
- MyBatis中的条件判断单引号双引号的使用
对于字符串判断, <if test="aIn != 'A'" >会出现问题,系统会试图把'A'转成数字,改为 <if test='aIn != "A&q ...
- jQuery css,position,offset,scrollTop,scrollLeft用法
jQuery css,position,offset,scrollTop,scrollLeft用法: <%@ page language="java" import=&quo ...
- spring mvc ajax请求
jar包中增加 jackson-annotations-2.5.0.jar jackson-core-2.5.0.jar jackson-databind-2.5.0.jar springmvx.xm ...
- StringUtils工具类常用方法介绍(持续更新)
StringUtils方法的操作对象是java.lang.String类型的对象,是JDK提供的String类型操作方法的补充,并且是null安全的(即如果输入参数String为null则不会抛出Nu ...
- sqlcmd命令导入大容量的SQL本地文件至SQL server 2008
由于开发工作在测试环境,需要构造测试数据,经常遇到100+M大小的*.sql文件需要导入到测试库的情况,由于SSMS里对导入文件的大小有限制: 会出现上图的报错!上网查了下,超过80M的文件是不能在S ...