数据访问层简单介绍

数据访问层,提供整个项目的数据访问与持久化功能。在分层系统中所有有关数据访问、检索、持久化的任务,最终都将在这一层完成。

来看一个比较经典的数据访问层结构图

大概可以看出如下信息

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的更多相关文章

  1. 企业级应用架构(三)三层架构之数据访问层的改进以及测试DOM的发布

    在上一篇我们在宏观概要上对DAL层进行了封装与抽象.我们的目的主要有两个:第一,解除BLL层对DAL层的依赖,这一点我们通过定义接口做到了:第二,使我们的DAL层能够支持一切数据访问技术,如Ado.n ...

  2. 项目架构开发:数据访问层之Logger

    接上文 项目架构开发:数据访问层之Cache 本章我们继续ILogger的开发 ILogger.cs public interface ILogger { void Info(object messa ...

  3. 项目架构开发:数据访问层之Repository

    接上文 项目架构开发:数据访问层之Logger 本章我们继续IRepository开发,这个仓储与领域模式里边的仓储有区别,更像一个工具类,也就是有些园友说的“伪仓储”, 这个仓储只实现单表的CURD ...

  4. 项目架构开发:数据访问层之UnitOfWork

    接上文 项目架构开发:数据访问层之IQuery 本章我们继续IUnitOfWork的开发,从之前的IRepository接口中就可以看出,我们并没有处理单元事务, 数据CUD每次都是立即执行的,这样有 ...

  5. 项目架构开发:数据访问层之Query

    接上文 项目架构开发:数据访问层之Repository 上一章我们讲了IRepository接口,这张我们来讲IQuery 根据字面意思就可以知道,这次主要讲数据查询,上一章我们只针对单表做了查询的操 ...

  6. 随机获得MySQL数据库中100条数据方法 驾照题库项目 MVC架构 biz业务层的实现类 根据考试类型rand或order通过dao数据访问层接口得到数据库中100或全部数据

    package com.swift.jztk.biz; import java.util.Collections; import java.util.Comparator; import java.u ...

  7. 数据访问层之Repository

    数据访问层之Repository   接上文 项目架构开发:数据访问层之Logger 本章我们继续IRepository开发,这个仓储与领域模式里边的仓储有区别,更像一个工具类,也就是有些园友说的“伪 ...

  8. asp.net/wingtip/创建数据访问层

    一. 什么是数据访问层 在wingtip项目中,数据访问层是对以下三者的总称:1. product类等数据相关的实体类(class)2. 数据库(database),对实体类成员的存储3. 上述二者的 ...

  9. servlet层调用biz业务层出现浏览器 500错误,解决方法 dao数据访问层 数据库Util工具类都可能出错 通过新建一个测试类复制代码逐步测试查找出最终出错原因

    package com.swift.jztk.servlet; import java.io.IOException; import javax.servlet.ServletException; i ...

随机推荐

  1. JS内存泄漏排查方法——Chrome Profiles

    一.概述 Google Chrome浏览器提供了非常强大的JS调试工具,Heap Profiling便是其中一个.Heap Profiling可以记录当前的堆内存(heap)快照,并生成对象的描述文件 ...

  2. Python3基础 global关键字 使函数的局部变量升格为全局变量

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...

  3. Java元注解

    元注解是指注解的注解,包括@Retention @Target @Document @Inherited四种. 1.@Retention: 定义注解的保留策略@Retention(RetentionP ...

  4. HTML5 + AJAX ( 原生JavaScript ) 异步多文件上传

    这是在上篇 HTML5 + AJAX ( jQuery版本 ) 文件上传带进度条 的修改版本.后台代码不变就可以接着使用,但是脚本不再使用jQuery了,改为原生的 JavaScript 代码,所以我 ...

  5. 解剖 Elasticsearch 集群 - 之三

    解剖 Elasticsearch 集群 - 之三 本篇文章是一系列涵盖 Elasticsearch 底层架构和原型示例的其中一篇.在本篇文章中,我们会讨论 Elasticsearch 如何提供准实时搜 ...

  6. MyBatis中的条件判断单引号双引号的使用

    对于字符串判断, <if test="aIn != 'A'" >会出现问题,系统会试图把'A'转成数字,改为 <if test='aIn != "A&q ...

  7. jQuery css,position,offset,scrollTop,scrollLeft用法

    jQuery css,position,offset,scrollTop,scrollLeft用法: <%@ page language="java" import=&quo ...

  8. spring mvc ajax请求

    jar包中增加 jackson-annotations-2.5.0.jar jackson-core-2.5.0.jar jackson-databind-2.5.0.jar springmvx.xm ...

  9. StringUtils工具类常用方法介绍(持续更新)

    StringUtils方法的操作对象是java.lang.String类型的对象,是JDK提供的String类型操作方法的补充,并且是null安全的(即如果输入参数String为null则不会抛出Nu ...

  10. sqlcmd命令导入大容量的SQL本地文件至SQL server 2008

    由于开发工作在测试环境,需要构造测试数据,经常遇到100+M大小的*.sql文件需要导入到测试库的情况,由于SSMS里对导入文件的大小有限制: 会出现上图的报错!上网查了下,超过80M的文件是不能在S ...