数据访问层简单介绍

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

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

大概可以看出如下信息

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. beforeunload

    <!DOCTYPE html> <html> <head> <title>BeforeUnload Event Example</title> ...

  2. VPS 上ubuntu 里搭建VPN服务器

    根据https://my.oschina.net/isnail/blog/363151里逐步完成,自己本机WIN10连接不成功,VM里面用WIN7连接也不行,找别人试连却成功了,然后自己用手机4G网络 ...

  3. 1.3.2. App Icon 和 Launch Image(Core Data 应用程序实践指南)

    App Icon: 选中 Assets.xcassets 选择 AppIcon ,并拖入图片(29.40.60) Launch Image: 创建 Launch Image 拖入图片(2x.R4)

  4. Webx MVC分析(转)

    Webx框架:http://openwebx.org/ petstore:webx3/webx-sample/petstore/tags/3.0/petstore 编译之后:mvn jetty:run ...

  5. 上传预览 easyui部分控件获取focuse 表单验证

    js: $(document).ready(function () { //$('#creater').combobox({ // url: '/VMS.UI/BindData/ScheamData? ...

  6. LCA 倍增

    最近公共祖先 对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. #include<cstdio> #include&l ...

  7. Spring的 classpath 通配符加载配置文件

    http://www.cnblogs.com/taven/archive/2012/10/24/2737556.html classpath:app-Beans.xml 说明:无通配符,必须完全匹配 ...

  8. POJ3254(入门状态压缩dp)

    Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13203   Accepted: 6921 Desc ...

  9. 作为测试人员,我是这么报BUG的

    在测试人员提需求的时候,大家经常会看到,测试员和开发一言不合就上BUG.然后开发一下就炸了,屡试不爽,招招致命. 曾经看到有个段子这么写道: 不要对程序员说,你的代码有BUG. 他的第一反应是:1.你 ...

  10. requireJS的初步掌握

    前一段时间,因为一些事吧这个习惯落下了,现在争取重新捡起来. 最近开始自学requireJS,为了更好的掌握,所以写出一个自我理解的博客供参考. 分割线------------------------ ...