AccEAP架构介绍(1)---实体的设计
刚刚看到阿木的 与DotNet数据对象结合的自定义数据对象设计 (一) ,讨论数据对象的设计思想,我就AccEAP中本人的实体设计思路参与讨论。
几个开源中, 阿木也提到 IBatisNet、NHibernate是 使用自定义数据类,而且他认为”这样就有点偏离DotNet的味道了,而在需要的时候再通过一些方法去转换得到DotNet数据对象,就显得麻烦而且复杂得多“, 呵呵,那阿木可以看看 EasyObject,它是微软推荐数据集强类想化的做法,不过是在DataTable上做的。
但我一直觉得利用DotNET数据对象不是很爽,尤其在分布式架构下。当初进行Remoting 技术测试的时候,我们做了几个试验,其中之一就是对一张10000条记录的表,分别用自定义类数组传输和用数据集(DataSet)传输,传输时间和流量的对比结果另人吃惊: (我只记得结果是差了一个数量级的,但现在在家里写作,测试数据在公司,我明天一早会来更新这里,把测试结果给出来)
现在分布式系统的瓶颈更多在于对象序列化和网络开销,即使是一个客户端,机器性能对处理自定义对象于数据集的转化应该不在话下, 于是认定AccEAP架构中数据对象的包装要用自定义类。然后也是 “在需要的时候再通过一些方法去转换得到DotNet数据对象”做法了,但只要做的恰当,似乎不会 ““显得麻烦而且复杂得多”。
OK。观点既出。
我更喜欢把这里的数据对象叫做实体,似乎好像还是应该有些概念上的区别哦,先不管了。下面详细讨论一下AccEAP的实体体系结构,分 实体定义,实体容器,实体持久化,实体界面绑定,实体缓存几个方面讨论吧。
一: 实体定义
实体肯定要有一些统一的东西,比如要具备 比较 和 深度克隆的能力,要能标志出实体的基本状态(标准,更改,删除)等等,所以,基本实体类还是需要的,于是有了下面的基本的实体类(其他实体提供的能力暂时不表)
[Serializable]
public abstract class EntityBase : IComparable, IDeepCopy
{
// public int iFChanged=0; //记录该类中的数据是否改变1:是,0:否
private EntityState _iStyle = EntityState.Add;//该条记录状态0:无变化,1:增加,2:修改,3:删除,
// private bool _IsNew = true;
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
实体状态控制
![](/Images/OutliningIndicators/InBlock.gif)
实体构造器
![](/Images/OutliningIndicators/InBlock.gif)
实体比较和复制
![](/Images/OutliningIndicators/InBlock.gif)
实体ID
}
这里有人提议过也给实体抽象出一个接口来,我认为没必要,因为接口是用来抽象服务的,这里的实体仅是对数据的封装,不提供任何的服务(方法),在实体管理中,直接用实体的基类就可以了。
特定实体在继承该类后,有了基本这些功能,剩下的就是专注自己的属性了,这些工作当然不需要手工去做的了,交给CodeSmith 之类的代码生成工具就OK了,一个简单示例:
[Serializable()]
public partial class Entity_AccEAP_LOG:EntityBase
{
public Entity_AccEAP_LOG()
{
// TODO: 在此处添加构造函数逻辑
}
private int _LOGID=new int();
private DateTime _LOGTIME=System.DateTime.Now;
private string _MEMO="";
private int _LOGTYPE=new int();
private int _SESSION_ID=new int();
![](/Images/OutliningIndicators/InBlock.gif)
/// <summary>
///
/// </summary>
public int LOGID
{
get
{
return _LOGID;
}
set
{
if (State != EntityState.Add)
State = EntityState.Amend;
_LOGID = value;
}
//剩下的属性省略
}
几个开源中, 阿木也提到 IBatisNet、NHibernate是 使用自定义数据类,而且他认为”这样就有点偏离DotNet的味道了,而在需要的时候再通过一些方法去转换得到DotNet数据对象,就显得麻烦而且复杂得多“, 呵呵,那阿木可以看看 EasyObject,它是微软推荐数据集强类想化的做法,不过是在DataTable上做的。
但我一直觉得利用DotNET数据对象不是很爽,尤其在分布式架构下。当初进行Remoting 技术测试的时候,我们做了几个试验,其中之一就是对一张10000条记录的表,分别用自定义类数组传输和用数据集(DataSet)传输,传输时间和流量的对比结果另人吃惊: (我只记得结果是差了一个数量级的,但现在在家里写作,测试数据在公司,我明天一早会来更新这里,把测试结果给出来)
现在分布式系统的瓶颈更多在于对象序列化和网络开销,即使是一个客户端,机器性能对处理自定义对象于数据集的转化应该不在话下, 于是认定AccEAP架构中数据对象的包装要用自定义类。然后也是 “在需要的时候再通过一些方法去转换得到DotNet数据对象”做法了,但只要做的恰当,似乎不会 ““显得麻烦而且复杂得多”。
OK。观点既出。
我更喜欢把这里的数据对象叫做实体,似乎好像还是应该有些概念上的区别哦,先不管了。下面详细讨论一下AccEAP的实体体系结构,分 实体定义,实体容器,实体持久化,实体界面绑定,实体缓存几个方面讨论吧。
一: 实体定义
实体肯定要有一些统一的东西,比如要具备 比较 和 深度克隆的能力,要能标志出实体的基本状态(标准,更改,删除)等等,所以,基本实体类还是需要的,于是有了下面的基本的实体类(其他实体提供的能力暂时不表)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
这里有人提议过也给实体抽象出一个接口来,我认为没必要,因为接口是用来抽象服务的,这里的实体仅是对数据的封装,不提供任何的服务(方法),在实体管理中,直接用实体的基类就可以了。
特定实体在继承该类后,有了基本这些功能,剩下的就是专注自己的属性了,这些工作当然不需要手工去做的了,交给CodeSmith 之类的代码生成工具就OK了,一个简单示例:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
没什么特别的东西,需要说明的也就是 在类的定义的时候用了 partial 关键字,对了,这是个局部类,很喜欢DotNET的这个功能,一个类可以在多个地方定义。为什么用这个: 我们刚从提到了,所有的数据实体的编码都是 自动生成的,但凡事都要考虑有其特殊性,有的实体可能仅仅这样不太够用,就可以在别处去补充这个实体的定义,注意是在别处,这样和自动生成的代码分离了,当然对维护大有裨益。类似的做法,我基本在所有的由代码生成的类中都运用了,后面讲到数据库元数据封装时就能体会这种好处。
好了,实体定义基本结束,没有给它额外的能力,仅仅是自身的状态标志和 数据的封装。到现在基本还没让各位朋友看出有什么特别的地方,还要耐心。
实体是要贯穿数据持久化,业务处理,界面现实的,和这些功能处理的搭配方式决定了系统的开发方式。首要的是要有一个容器,来进行实体对象的基本管理工作,这是个重要的东西。
待续。。。