代码改变世界

NET 应用架构指导 V2 学习笔记(十三) 数据访问层指导

2010-06-02 13:21  Virus-BeautyCode  阅读(2242)  评论(0编辑  收藏  举报
  
  数据访问层简介
 
  
  上图的深黑色框中的就是数据访问层,通常包括下面的部分:
  数据访问组件。这些组件抽象了对于存储在数据库的内容的访问。将常用的数据访问集中化,是的应用很容易配置和维护。一些数据访问框架,还允许开发者在helper和数据访问组件的基础上实现自定义的访问组件。其他的数据访问组件,例如ORM框架,自动实现了数据访问组件,减少了开发者需要编写的数据访问代码。
  服务代理。如果业务逻辑需要访问一个来自其他服务提供的数据,需要为特殊的服务实现一些代理访问的代码。服务代理需要开发者实现对于服务的访问,还需要缓存,离线支持,基本的数据映射(应用可用的数据格式与服务提供的数据格式之间映射)。
  通常的设计考虑
  你的数据访问层一定要满足应用的需要,高效的、安全的运行,如果逻辑层变化的话,很容易维护和扩展。在设计的时候,可以参考下面的原则:
  •   选择适当的数据访问技术。数据访问技术的选择依赖于你处理的数据类型,在应用中如何操作数据。特定的数据访问方案更加适合特定的方案。
  •   使用抽象实现松散耦合的数据访问层接口。通过定义接口组件来实现,就好像网关的输入和输出,将请求翻译成一个可以被组件理解的格式。另外,你可以使用接口类型或者是抽象类型定义共享的接口。
  •   在数据访问层封装数据访问功能。数据访问层应该隐藏对数据存储的访问细节。负责管理链接,生成查询,将实体映射为数据存储的类型。数据访问层的消费者,应该使用数据实体和数据访问层进行交互,不应该知道内部的实现细节。分离关注,有利于应用开发和维护。
  •   决定如何从实体映射到数据源的结构。通常使用Domain Model或者是Table Module模式,或者使用ORM框架。
  •   考虑使用巩固的数据结构。如果你通过服务暴露数据,考虑使用DTO帮助你统一数据格式。另外,DTO鼓励粗粒度的操作,提供一个可以在不同的边界之间传递数据的结构。如果你使用Table Data Gateway 或者是Active Record模式,可以考虑使用DataTable来代表数据。
  •   决定如何管理链接。数据访问层应该创建和管理所有的数据访问连接。一定要选择一个合适的方法存储和保护连接信息,可以通过加密配置节的链接信息。
  •   决定你如何处理数据异常。数据访问层应该捕获和处理和数据源以及CRUD(Create,Read,Update,Delete)操作的异常。异常集中在数据本身,对数据源的访问,访问超时,应该在本层处理,如果异常影响到应用的功能,需要向上层传递。
  •   考虑安全风险。数据访问层保护数据,防止攻击,试图获取或者是破坏数据。例如:审查错误和异常信息,不要将这些信息暴露,使用最小级别的账户限制获取更多的信息。在数据源和数据访问层都要显示账户的权限。通过参数化查询条件,防止SQL注入攻击,不要使用用户出入的内容进行字符串拼接。
  •   减少数据库的往复。考虑在一次数据库查询中批量执行命令,减少和数据库的往复。
  •   考虑对象的性能和伸缩性。在设计的时候就要考虑对象的伸缩性和性能。例如:如果是跨越internet的应用,数据访问层很可能就是应用的瓶颈。如果数据访问性能很关键,优化数据访问,减少数据操作带来的性能消耗。
  特殊的设计问题
  在设计数据访问层的时候,通常有下面的问题需要面对:
  •   批量的问题
  •   大型的二进制对象
  •   连接
  •   数据格式
  •   异常管理
  •   对象关系映射
  •   查询
  •   存储过程
  •   存储过程 还是 动态SQL语句
  •   事务
  •   验证
  •   XML
  1 批量的问题
  批量执行数据库命令可以提高数据访问层的性能。每一次数据库执行,都会引来性能的消耗。通过增加吞度量和减少延迟,批量处理可以减少总的消耗。一些相似的命令批量执行可以提高性能,因为数据库缓存,重用一个相似查询的执行计划。在设计批量的时候可以参考下面的原则:
    •   使用批量减少数据库往复和网络通信量。但是,批量类似的查询才可以获得最大的性能提高。批量不相似的、或者是随机的查询,和批量类似的查询,不提供相同级别的性能提高。
    •   考虑用批量命令和DataReader获取数据。如果要从文件中加载大量数据到数据库,考虑使用BCP(Bulk Copy Utilities)。
    •   在需要长时间运行的批量命令中不要使用事务, 会锁定数据库资源。
  2 大型的二进制对象
  当数据的存储和获取以单一的流为单位的时候,考虑使用大型的二进制对象,BLOB(Binary Large Object),数据的结构对于数据库是不可见的,数据访问层也只是读取和写入这个数据。在数据库直接存放他们,或者存储一个指向他们的指针,通常不直接存储在数据库,而是存放在文件系统。通常用来存储图片数据,或者是存储对象的二进制形式,可以参考下面的原则:
  考虑是否要将BLOB存储在数据库。现在的数据库对于处理BLOB更加好了,提供你可以选择的适当的列类型,提供可维护性,版本,操作和相关的元数据。但是要考虑存储在硬盘上是否更合适,在数据库只是存储一个地址。
  考虑使用BLOB简化大型的二进制数据在服务器之间的同步。
  考虑对于BLOB是否需要搜索。如果需要的话,建立其他的列用来查询,而不是查询二进制数据本身。
  什么时候需要获取BLOB数据,在业务层或者是表现层将它转换为适当的类型。
  3 连接
  连接是数据访问层的一个基础部分,所有的数据源访问连接都应该在数据访问层管理。为了最大化性能和安全,可以参考下面的原则:
    •   通常来说,打开的链接应该尽早的关闭。不要长期的将连接处于打开状态。
    •   无论什么时候,都通过一个连接进行事务的操作。  
    •   使用连接池。
    •   处于安全原因。避免使用系统或者是User Data Source Name(DSN)存储连接信息。
    •   考虑在连接丢失或者超时的时候,是否设计提供冲重新尝试的功能。
  4 数据格式
  和其他应用进行交互的时候,选择适当的数据格式,跨进程和物理机器的时候使用序列化。可以参考下面的设计原则:
  •   在和其他系统或者平台进行交互的时候,考虑使用xml格式的数据。
  •   在简单的CRUD为基础的应用中,考虑使用离线方案的DataSets。
  •   如果你一定要跨物理边界传输数据,考虑序列化。例如:考虑如何序列化自定义的业务对象,在需要的时候如何将他们翻译成DTO,接受数据的层可以理解什么格式的数据。
  5 异常管理
  设计一个集中的异常管理策略,方便在数据访问层保持一致的异常捕获和抛出。如果有可能的话,将异常处理组件化,实现跨层的关注。特别关注一下异常在可信边界与其他层之间的传递。为不能处理的异常进行设计,以便不会导致系统的可用性问题,不会暴露系统的敏感信息。参考下面的设计原则:
  •   确定应该在数据访问层捕获和处理的异常。例如:死锁和连接问题应该在数据访问层处理。但是,一些并发的问题,应该让用户来决定。
  •   设计一个适当的异常传播策略。例如:允许异常传播到可以记录的层。
  •   考虑实现一个在发生异常的时候,可以重新尝试的功能。
  •   设计记录异常信息的发生,同时不暴露敏感信息,方便查找系统的错误。
  6 对象关系映射
  在设计面向对象应用的时候,考虑阻止OO模型和关系模型之间的不匹配,考虑他们之间转换的难点。例如:OO设计中的封装,隐藏字段的地方,和数据库的开放的天性不匹配。还有就是数据类型的不一致,结构不一致,处理不同,数据操作也不一致。有两个常用的办法来处理这类问题,一个是Repository模式,一个是ORM工具。Domain Driven Design领域驱动的设计方法,一个以领域对象为实体类,经常是一个合适的选择。可以参考下面的设计原则:
  •   考虑使用提供实体和数据库之间的ORM的框架,现在的ORM框架可以帮助减少大量需要编写的代码。
  •   如果你工作在一个全新的开发环境,对数据库有完全的控制,你可以用ORM工具生成对象模型对应的数据库结构,提供对象模型和数据库之间的映射。
  •   如果你工作在一个正在运行的环境,已经存在一个数据库结构,你也可以用ORM工具生成对应的对象模型。
  •   如果你工作在一个小应用,或者是没有权限使用ORM工具,实现一个常用的数据访问模型,例如:Repository。
  •   当开发web应用和web service的时候,考虑使用延迟加载。允许应用优先处理优先级高的用户请求。
  
 
  未完待续。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。