项目架构开发:数据访问层之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 ...
随机推荐
- Core Data使用之一(Swift): 获取
//获取entity中的数据 func fetchFiles() { //第一步,获取总代理 let appDelegate = UIApplication.sharedApplication().d ...
- mysql 和excel相互转换
原文地址:http://blog.sina.com.cn/s/blog_43eb83b90100h0mc.html 今天是全国数学建模比赛,同学选的一个题目需要对一个large的Excel表格进行统计 ...
- AC日记——统计难题 hdu 1251
统计难题 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)Total Submi ...
- php常用图片处理类
<?php /** * 已知问题:1.在图片缩放功能中,使用imagecreatetruecolor函数创建画布,并使用透明处理算法,但PNG格式的图片无法透明.用imagecreate函数创建 ...
- C++风格写判断某年某月某日是一年的第几天
初学C++,在结构体中写函数及一些C++语言需要的一些格式 看代码 #include<iostream>#include<cstdio>using namespace std; ...
- JQuery flot API文档 中文版
调用plot函数的方法如下: var plot = $.plot(placeholder, data, options) 其 中placeholder可以是JQuery的对象,DOM元素或者JQuer ...
- 添加Action View
ActionBar上除了可以显示普通的Action Item之外,还可以显示普通的UI组件.为了在ActionBar上添加ActionView,可以使用如下两种方式. 定义ActionItem时使用a ...
- 滚动视图(ScrollView)的功能与用法
滚动视图ScrollView由FrameLayout派生而出,它就是一个用于为普通组件添加滚动条的组件.ScrollView里最多只能包含一个组件,而ScrollVew的作用就是为该组件添加垂直滚动条 ...
- 每一个Servlet只有一个实例,多个线程
每一个Servlet只有一个实例,多个线程: Servlet: package com.stono.servlet.synchronize; import javax.servlet.http.Htt ...
- Spring事务配置的五种方式和spring里面事务的传播属性和事务隔离级别
转: http://blog.csdn.net/it_man/article/details/5074371 Spring事务配置的五种方式 前段时间对Spring的事务配置做了比较深入的研究,在此之 ...