原文:[原创].NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇)

.NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇)

  前言:上一篇文章讲述了一些实现DAL的理论,本篇主要是DAL实现的的初步的尝试。

  本篇的主要议题如下:

  1. 设计DAL的基本操作

  2. 对基本的操作的进一步的思考

  3. 查询对象的一些思考

  系列文章链接:

[原创].NET 分布式架构开发实战之一 故事起源

[原创].NET 分布式架构开发实战之二 草稿设计

[原创].NET 分布式架构开发实战之三 数据访问深入一点的思考

[原创].NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇)

[原创].NET 分布式架构开发实战五 Framework改进篇

[原创].NET 业务框架开发实战之六 DAL的重构

[原创].NET 业务框架开发实战之七 业务层初步构想

[原创].NET 业务框架开发实战之八 业务层Mapping的选择策略

[原创].NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略

[原创].NET 业务框架开发实战之十 第一阶段总结,深入浅出,水到渠成(前篇)

[原创].NET 业务框架开发实战之十 第一阶段总结,深入浅出,水到渠成(后篇)

  1. 设计DAL的基本操作

Richard认为:在设计一个架构或者Framework的时候,有几点很重要:

  a. 总体把握的能力。

  b. 抽象的能力。

  c. 分析的能力

首先,从总体上来看,Richard认为DAL中最基本,而且最容易想到的方法就是CRUD(Create, Read, Update, Delete)四个操作。

于是Richard在草纸写出了基本操作的名称:

AddSingleDataEntity;

AddDataEntityList;

UpdateSingleDataEntity;

UpdateDataEntityList;

DeleteSingleDataEntity;

DeleteDataEntityList;

GetSingleDataEntiry;

GetDataEntityList;

上面列出的方法名字很长,其实Richard在思考这些方法的名称的时候也参考了.NET设计规范中的一些建议:方法名称要具有“自解释性”,因为架构的设计最后还是给开发人员用的,所以方法的定义要一眼就看出它是干什么的,而且规范的命名也可以大大的减少维护的成本。(可能这些名字的命名有点对规范的“生搬硬套”,但是之后会慢慢的重构的)

从总体出发,已经定义出了基本的操作,那么现在就开始一步步的分析,如何实现这些方法。

Richard开始思考第一个方法的实现,其实Richard心里也清楚:其实到底哪个方法作为第一个来考虑也许很重要,但是在一切都不清楚之前起码要拿一个来入手,而且随着思考的深入,很多的问题都会慢慢的浮现,到时候一切就会明晰起来。

对于AddSingleDataEntity这个方法,首先就要考虑这个方法到底要把什么添加到数据库中,也就是说要考虑这个方法的参数,而且这个参数要足够的“兼容”,因为之前Richard就是想设计出一个“以不变应万变”的DAL。在考虑这个参数问题之前,首先Richard很清楚:在.NET数据访问技术中,Linq,Entity Framework等ORM技术已经广泛的应用,所以在设计DAL的时候要充分的考虑到现有的一些技术(尽量避免重新造轮子)。

而且在数据是如何被存入到数据库中的以及数据是如何从数据库中取出的,这个工作是完全可以交给这些ORM的,最后的结果就是:在DAL中只是操作这些ORM的那些映射实体。基于这个想法, Richard就确定了:AddSingleDataEntity参数是一个数据实体。(本系列文章约定:数据实体,即DataEntity,就是ORM对一个数据库表进行映射后产生的实体和数据库中的表一一对应,如在数据库中有一张Employee表,Linq to Sql将会把它映射成为Employee的一个类,这个类就称为数据实体)。因为这些方法最终是操作数据实体的,所以包含这些方法的接口名字就定义为IDataContext

因为不同的表产生不同的数据实体,但是Richard还想使得AddSingleDataEntity这个方法可以接受任何的数据实体,所以此时很有必要对数据实体进行抽象。所以Richard想到了定义一个接口:IDataEntity,打算让所有通过ORM生成的数据实体都继承这个接口。而且Richard还想到:

  1. 如果BLL直接引用DAL使用的,那么IDataEntity可能会在BLL中出现的。

  2. 如果BLL通过repository去DAL中获取数据,那么到时候BLL可能都不会直接引用DAL,但是BLL最终还是得使用数据做事情,所以IDataEntity还是会在BLL中出现,所以,IDataEntity接口最好定义在一个公共的地方。

  Richard决定新建一个Common的类库,加入IDataEntity接口的定义,现在这个接口里面什么都没有,只是一个标记而已,表明继承这个接口的类就是数据实体类。

    AddSingleDataEntity(IDataEntity dataEntity);

  还有一点就是尽量的使用类型安全的方法,于是Richard把方法改成了范型方法:

    AddSingleDataEntity<T>(T dataEntity) where T:IDataEntity,class,new();

  至于T 的那些约束:T:IDataEntity,class,new(),是考虑到了Linq和EF中对数据实体的一些要求。

  一般的Add方法都是返回添加是否成功,true或者false,方法再次改造:

    bool AddSingleDataEntity<T>(T dataEntity) where T:IDataEntity,class,new();

  然后Richard就写出了上面列出的一些方法的定义:

     bool AddSingleDataEntity<T>(T dataEntity) where T : class,IDataEntity, new();

    bool AddDataEntityList<T>(List<T> dataEntityList) where T : class,IDataEntity, new();

    bool DeleteDataEntityList<T>(List<T> dataEntityList) where T : class,IDataEntity, new();

    bool DeleteSingleDataEntity<T>(T dataEntity) where T : class,IDataEntity, new();

    bool UpdateSingleDataEntity<T>(T dataEntity) where T : class,IDataEntity, new();

    bool UpdateDataEntityList<T>(List<T> dataEntityList) where T : class,IDataEntity, new();

  至于GetDataEntityList,按照之前的查询对象的想法,传入一个IQuery的接口:

    List<T> GetDataEntityList<T>(IQuery query)where T : class,IDataEntity, new();

  2. 对基本的操作的进一步的思考

  确实,上面那些基本操作是没有什么问题的,现在Richard又考虑到了另外的一些问题,还是以AddSingleDataEntity方法为例:

    a. 有些时候,不仅仅要知道插入数据是否成功,而且还想返回新加入数据在数据库中的主键信息来做其他的用途。怎么办?再来查询一次?

    b. 如果插入失败了,仅仅只是返回一个false吗?可能其他的调用模块想知道到底是发生了什么异常而导致的插入失败,而且其他的模块对于发生的异常有自己的处理方法,所以AddSingleDataEntity要提供足够的信息。

  基于上面的思考,所以这个基本的操作方法不能只是简单的返回一些简单的值就完了。也就是说,这些方法要返回一个数据包:里面包含很多信息,以便其他的调用模块来使用这些信息,感觉有点像是C#事件中的eventArgs.

所以Richard在Common的那个类库中加入一个对象,定义如下:

代码
public class DataResult<T> where T : IDataEntity
    {

        public List<T> EntityList { get; set; }

        public bool IsSuccess { get; set; }

        public Exception Exception { get; set; }

        public object CustomData { get; set; }

    }

  这个类最后将会作为方法的返回结果。

  Richard发觉,上面的方法确实是很有”自解释性”,但是很多的开发人员对这些CRUD操作的名字都很熟悉了,而且最后开发的出来的架构的使用者还是开发人员,应该符合他们的习惯,所以Richard改变了方法的名字,改变后的版本如下:

代码
 public interface IDataContext
    {
        IList<T> Query<T>(IQuery queryCondition) where T : class,IDataEntity, new();
        IList<T> Query<T>(IQuery queryCondition, int pageIndex, int pageCount) where T : class,IDataEntity, new();

        // CRUD services (well, mostly CUD)
        T Add<T>(T item) where T : class,IDataEntity, new();
        IList<T> Add<T>(List<T> itemList) where T : class,IDataEntity, new();
        bool Delete<T>(List<T> itemList) where T : class,IDataEntity, new();
        bool Delete<T>(T item) where T : class,IDataEntity, new();
        T Update<T>(T item) where T : class,IDataEntity, new();
        List<T> Update<T>(List<T> itemList) where T : class,IDataEntity, new();

    }

  3. 查询对象的一些思考

  在上面的基本的操作中,在Query方法中传入的是查询对象,因为查询对象是基于解释器的,可以在解释完查询对象之后就缓存起来。以后再次查询的时候,如果两个查询的对象一样(例如在构造查询对象时候,可以为其定义一个唯一的标示),那么就不用再去对查询对象进行解释。如果根据这个查询对象的查出的数据都是只读的,那就更好了,就可以把查询对象和对应的结果一起缓存起来。

  今天就先写到这里了,下一篇:

  .NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(中篇)—DAL的基本方法的重构

  谢谢各位!

[原创].NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇)的更多相关文章

  1. [原创].NET 分布式架构开发实战五 Framework改进篇

    原文:[原创].NET 分布式架构开发实战五 Framework改进篇 .NET 分布式架构开发实战五 Framework改进篇 前言:本来打算这篇文章来写DAL的重构的,现在计划有点改变.之前的文章 ...

  2. [原创].NET 分布式架构开发实战之三 数据访问深入一点的思考

    原文:[原创].NET 分布式架构开发实战之三 数据访问深入一点的思考 .NET 分布式架构开发实战之三 数据访问深入一点的思考 前言:首先,感谢园子里的朋友对文章的支持,感谢大家,希望本系列的文章能 ...

  3. [原创].NET 分布式架构开发实战之二 草稿设计

    原文:[原创].NET 分布式架构开发实战之二 草稿设计 .NET 分布式架构开发实战之二 草稿设计 前言:本篇之所以称为草稿设计,是因为设计的都是在纸上完成的.反映了一个思考的过程. 本篇的议题如下 ...

  4. [原创].NET 分布式架构开发实战之一 故事起源

    原文:[原创].NET 分布式架构开发实战之一 故事起源 .NET 分布式架构开发实战之一 故事起源 前言:本系列文章主要讲述一个实实在在的项目开发的过程,主要包含:提出问题,解决问题,架构设计和各个 ...

  5. NET 分布式架构开发项目实战

    .NET 分布式架构开发项目实战 从头到尾,一步一步讲述一个真实的项目实战,关注点主要是架构的思考和实现,以及如何解决平时项目遇到的一些问题. 同时也司公布源代码. 如何构建高性能,稳定SOA应用之- ...

  6. [原创].NET 业务框架开发实战之十 第一阶段总结,深入浅出,水到渠成(后篇)

    原文:[原创].NET 业务框架开发实战之十 第一阶段总结,深入浅出,水到渠成(后篇) .NET 业务框架开发实战之十 第一阶段总结,深入浅出,水到渠成(后篇) 前言:接着上篇来. 系列文章链接: [ ...

  7. [原创].NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略

    原文:[原创].NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略 .NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略 前言:之前的讨论一直关注在怎么从D ...

  8. [原创].NET 业务框架开发实战之八 业务层Mapping的选择策略

    原文:[原创].NET 业务框架开发实战之八 业务层Mapping的选择策略 .NET 业务框架开发实战之八 业务层Mapping的选择策略 前言:在上一篇文章中提到了mapping,感觉很像在重新实 ...

  9. [原创].NET 业务框架开发实战之七 业务层初步构想

    原文:[原创].NET 业务框架开发实战之七 业务层初步构想 .NET 业务框架开发实战之七 业务层初步构想 前言:本篇主要讲述如何把DAL和BLL衔接起来. 本篇议题如下: 1.       DAL ...

随机推荐

  1. Html A标签中 href 和 onclick用法、区别、优先级别

    原文:Html A标签中 href 和 onclick用法.区别.优先级别 如果不设置 href属性在IE6下面会不响应hover.双击后会选中标签的父容器而非这个一a标签(IE下都存在这一问题). ...

  2. C++ Primer 学习笔记_62_重载操作符与转换 --调用操作符和函数对象

    重载操作符与转换 --调用操作符和函数对象 引言: 能够为类类型的对象重载函数调用操作符:一般为表示操作的类重载调用操作符! struct absInt { int operator() (int v ...

  3. Android数字签名解析(二)

    在Android数字签名解析(一)中,介绍了android进行签名的两种方式,当中用密钥对进行签名用到了signapk.jar这个java库. 以下我们就看看signapk签名实现过程,signapk ...

  4. 怎样在万网加入Lync Online SRV记录

    万网已经支持SRV记录解析了,可是有好几个朋友问我怎么加入SRV记录(假设域名提供商不支持,能够通过DNSPOD来实现),过程例如以下 1:绑定域名至Office 365 略,请查看我的视频或者博客中 ...

  5. C语言 - printf的占位符(%) 异常

    printf的占位符(%) 异常 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26719135 C语言中, 使用%代表占位符的意 ...

  6. Java--调试--单步调试,断言,单元测试

    单步调试:主要查看变量内容的变化    1.设置断点位置,设置在可能出现问题的代码 2.以Debug as方式运行 程序 3.F5 --> step into 进入方法内部进行调试    F6 ...

  7. POJ 1274 The Perfect Stall 水二分匹配

    主题链接:id=1274">点击打开链接 呵呵 #include<cstdio> #include<cstring> #include<cstdlib&g ...

  8. 递归遍历XML所有节点

    package xml; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.DocumentEx ...

  9. IIS的WebGarden、WebFarm和StateServer

    开启IIS的WebGarden.WebFarm和StateServer之旅 前言 公司系统虽然配置有1台NLB后拖4台App Server最后搭一台强劲无比的DB Server,但每天下午4点左右总被 ...

  10. SQL Server 性能调优培训引言

    原文:SQL Server 性能调优培训引言 大家好,这是我在博客园写的第一篇博文,之所以要开这个博客,是我对MS SQL技术学习的一个兴趣记录. 作为计算机专业毕业的人,自己对技术的掌握总是觉得很肤 ...