`
coolerbaosi
  • 浏览: 729031 次
文章分类
社区版块
存档分类
最新评论

软件架构设计系列总结—8—数据访问层简述

 
阅读更多
在前面简单描述了下服务层,SOA面向服务架构,架构设计-业务逻辑层,以及一些面面向设计原则理解和软件架构设计箴言。这篇博客我们将继续进入我们的下一层:数据访问层。无论你用的是什么开发模式或者是业务模式,到最后最必须具有持久化机制,持久化到持久化介质,并能对数据进行读取和写入CRUD。这就是数据访问层。你可能是利用xml等文件格式磁盘存储,常用的关系数据库存储,或者NoSql(not only sql)的内存存储或文档存储等等存储介质。而这里我只关心关系数据库存储。

数据层需要提供的职责有:

1:CRUD服务。作为唯一可以与存储介质交互的中间层出现,负责业务对象的增加,修改,删除,加载。

2:查询服务。这不同于CRUD中的R(read),read倾向于的单个对象,元组。而这里的查询针对复杂查询,比如一个国内电商的客户为四川的订单。这里会涉及仓储层。所谓仓储模式指的是一个提供业务对象查询的类,他隐藏了数据查询的解析步骤,封装sql解析逻辑。

3:事务管理。这里所说的是业务事务,在一个应用系统中每次请求都会产生多次的多数据对象的新增,修改,删除操作。如果我们每次都依次代开数据库连接,准备数据包,操作数据库,关闭数据连接。这些将会给我们带来很多不必要的性能开销。数据库管理员经常会要求“尽量少的与数据库交互”,这也必须成为我们的开发原则。更好的操作是我们在内存中建立一个和数据仓库,维护变化的对象,在业务操作完成一次性提交到数据存储介质,提供业务事务。业务事务有个很好听的名字工作单元(UOW),在微软给我们提供的DataSet,orm框架都回必须存在业务事务。

4:并发处理。UOW应避免业务数据连接的多次提交打开而出现,但在内存离线操作,这就可能导致数据一致性问题。在多用户的环境,对数据并发处理需要制定一个策略。一般我们会采用乐观并发处理:用户可以任意的离线修改,在修改更新时候检查对象是否被修改,如果被修改者本次更新失败。简单的说就是防止丢失修改。防止丢失修改,我们可以采用where 加上一系列原值,或者加上修改时间戳或者版本号标记。同时还有许多其他的并发解决模式,但乐观并发锁用到更普遍。

5:数据上下文:整和所有职责。在数据访问层概念职责都会有一个共同的暴露给外部的接口。我们需要一个高层次的组件,来同一提供对数据存储介质的访问操作。,同一访问数据库CRUD,事务,并发服务的高层次类,叫做数据上下文(Context)。EF中的ObjectContext,NHibernate的session,linq to sql 的DataContext等等。

数据访问层的一些概念(这里不会是全部,仅一些个人觉得重要的概念):

1: 数据映射器:将内存中修改的对象提交至存储介质,则需要要映射逻辑来完成,数据映射器就是就是一个实现将某种类型的业务对象持久化的类(数据映射器模式定义如《P of EAA》)。

2:仓储层(Repository):在上面提到:所谓仓储模式指的是一个提供业务对象查询的类,他隐藏了数据查询的解析步骤,封装sql解析逻辑。在面向对象的世界里我们用对象进行查询,返回结果为对象集。这里的查询可能是从数据库,或者来至缓存,这取决你的策略,你仓储层的实现。

3:工作单元(UOW):Martin Fowler《P of EAA》 定义:工作单元记录在业务事务过程中对数据库有影响的所有变化。操作结束后,作为一种结果,工作单元了解所有需要对数据库做的改变。在上面第3点业务事务讲的差不多,这里不是累述。

4:标示映射(Identity Map):其作用在于:便于跟踪业务对象,调用者在一个业务事务中使用的是同一个实例,而不是每次执行产生一个新的对象。表示映射为一个散列表存储(散列具有快速定位O(1))。类似于缓存的实现方式,保证了在同一个业务事务数据上下文引用修改同一个业务对象。但绝不同于缓存。从持续时间来说,标示映射生命周期为业务事务内。实现上等同于数据上下文期。但比起缓存来说其周期太短,根本不能对性能有多大的改善。缓存更重要的命中率,而标示映射保证同一数据上下文采用修改同一个业务对象的引用。

5:乐观并发锁:在上面也曾提到,其保证离线操作数据的对数据一致性的冲突解决方法。首先乐观在于允许离线操作,容忍冲突,防止数据丢失修改,可利用原读取数据值得where条件或者时间戳,版本号解决。

6:延时加载:对象并不是一次性加载完成,而是按照需求多次加载数据,到用时加载。业务对象太多关联,数据量太多余庞大,而我们每次业务事务需要操作的对象都只会是部分,不需要太多的数据对象。同事业务对象中还存在循环引用,这样不适于对象整体的一次性加载。延时加载提供了优化,意图在“尽可能的少加载,并按需加载,只加载需要的数据部分”。

7:持久化透明对象(PI或POCO):当对象模型不存在任何外部依赖,特别是对于数据访问层的依赖,那么这个模型就是持久化透明的,POCO。一个POCO的对象不需要继承至某个特定的类,实现特定的接口,或提供专门的构造函数。一个非持久化透明的对象这以为者存在外部的依赖,而我们更喜欢领域对象只是一个简单额c#类,可以在持久化层等独立切换。这就导致实现的时候我们无法很直接的跟踪业务对象,这就是面向方面编程(AOP)或者代理模式的大显身手。可惜AOP在.net中不是那么直接,很多ORM框架如NHibernate之类的利用代理模式Emit动态注入IL实现跟踪,添加新的行为。所以NHibernate中要求领域对象的所有字段属性方法都必须是虚方法可重写的。:

8:CQRS(Command Query Responsibility Segregation,命令查询职责分离):CQRS是在DDD的实践中引入CQS理论而出现的一种体系结构模式,命令和查询被分离。具体可以参 Martin Fowler的CQRS文章:http://martinfowler.com/bliki/CQRS.html

分享到:
评论

相关推荐

    程序开发原理:抽象、规格与面向对象设计.[美]Barbara Liskov(带详细书签).pdf

    该书的后7章主要讲述了怎样利用抽象构建大型软件,主要侧重于软件工程的内容,基于类型层次结构提出对于数据抽象的调试、测试、需求分析、自顶向下和迭代的开发过程,还简要介绍了设计模式的概念。 这是一本传授思想...

    asp.net知识库

    .NET的反射在软件设计上的应用 关于跨程序集的反射 实现C#和VB.net之间的相互转换 深入剖析ASP.NET组件设计]一书第三章关于ASP.NET运行原理讲述的补白 asp.net 运行机制初探(httpModule加载) 利用反射来查看对象中的...

    java 面试题 总结

    封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。 4. 多态性: 多...

    Android驱动开发权威指南

    18.3.2 Android Binder子系统的架构设计 18.4 Binder的工作流程 第19章USB子系统 19.1 USB协议基础知识 19.1.1 USB物理连接 19.1.2 USB通信协议 19.2 USB子系统底层 19.2.1 USB Core 19.2.2 Linux USB gadget三层...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【基础】访问修饰符区别 15 【基础】java基本数据类型(四类八种) 15 Java自动类型转换 16 数据类型自动提升(注意以下讨论的是二元操作符) 16 【基础】switch支持的类型 17 【基础】当一个对象被当作参数传递到一...

    net学习笔记及其他代码应用

    数据访问层对数据库进行增删查改。 业务层一般分为二层,业务表观层实现与表示层的沟通,业务规则层实现用户密码的安全等。 表示层为了与用户交互例如用户添加表单。 优点: 分工明确,条理清晰,易于调试,而且...

    超级有影响力霸气的Java面试题大全文档

     封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。 4. 多态性: ...

Global site tag (gtag.js) - Google Analytics