网语飘飘.Net/Delphi攻坚战

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::
一、 简要说明
为什么要创建实体与数据集对应关系呢?
猛禽兄有一篇技术文章告诉你。
http://borland.mblogger.cn/raptor/posts/14782.aspx


创建一个实体类,有多种方式,但我固执的认为,只声名不实现将是最简洁最好的方式。
这种方式将代码量减到最少,以后做一个代码生成工具,也方便代码复制粘贴。

比如,国家实体类声名如下:
TCountry = class(TgsDataSetProxy)
  published
    property Name: TStringF index 0 read GetStringF;
    property Capital: TStringF index 1 read GetStringF;
    property Continent: TStringF index 2 read GetStringF;
    property Area: TNumberF index 3 read GetNumberF;
    property Population: TNumberF index 4 read GetNumberF;
  end;
但不幸的是,必须用属性索引才能获知属性名称信息。说起缘由,还是Delphi的RTTI实现功能相对很弱,比如只能获知published声明的属性,不能在运行时获知记录类型元素信息,不能获知类的Pbulic声明信息等。

当实体字段顺序与数据集字段顺序不一致,在初始化实体实例时,TgsDataSetProxy 调用 CheckEntityDataSet:函数强制检验序号与名称是否一致。目前只是校验实体属性名与数据集字段名是否一致,未强制检验类型一致。

为了统一实体映射表字段规范,我创建了TstringF、TnumberF等六种字段。如果用简单类型实现实体字段,也无可厚非,但为了以后扩展方便,还是自定义实体字段类型对象较好一些。

比如TNumberF:
TNumberF = class(TgsPropField)
  private
    FValue: Double;
    procedure SetValue(const Value: Double);
    function GetStrValue: string;
  published
    property Name;
    property Caption;
    property AsNum: Double read FValue write SetValue;
    property ToStr: string read GetStrValue;
  end;
声明了一个属性AsNum,虽然敲写代码多了一些,但可以一目了然知道实体字段类型,另外也可以提供ToStr转换成字符串。

GetNumberF(Index:integer)在其父类TgsDataSetProxy的 protected声名,目的是实现实体类只声名不实现方式。

在TgsDataSetProxy实现了CURD功能,即简单的 Insert、Update和delete功能。

其实我最向往的定义实体元数据方式是,
TCountry = class(TgsDataSetProxy)
  published
    property Name: TStringF Read GetStringF;
    property Capital: TStringF Read GetStringF;
    property Continent: TStringF Read GetStringF;
    property Area: TNumberF Read GetNumberF;
    property Population: TNumberF Read GetNumberF;
property ContinentID: TContinent. read GetStringF;
property ContinentCaption: TlookupField(实体参数类名) read GetLookupField;//主要目的是实现Lookup关联数据集和字段。

end;
以上说的是一些思想而已,语法也肯定有错误,delphi按这样方式也未必能实现。
由于delphi没有.net的属性特性,直接实现很困难。
具体思想,可以参考我同事的SuperORM思想,虽然是.Net实现的,但看完他的文章思想,相信对你还是受益匪浅。
http://www.wbstudy.com/ViewTopic.aspx?ForumID=10&TopicID=2483

二、 参考文献
                  
参考代码:1.猛禽兄 <<用DELPHI的RTTI实现数据集的简单对象化>>
              详见猛禽兄的Blog
              http://borland.mblogger.cn/raptor/posts/14782.aspx

            2.Chris Lichti的delphi之 RTTI管理类,单元clRTTI就是
              他所写,我保留了他的原著,也不再注释成中文了

  参悟代码:3.我同事(绰号:大师)一个 .NET SuperORM 框架思想
              详见大师的个人学习网站
              http://www.wbstudy.com/

在此对他们表示由衷的感谢!!!
三、 扩展说明:
在理解猛禽兄的源码上,重写了实体数据集体对象化。扩展了实体的遍历、新增、修改和删除,即常用的CURD功能。如同猛禽兄所说的,要获得属性名称,只好利用属性索引,即index 0。
    我现在已开始 .NET项目开发,如果有时间,我会扩展一下功能:

    客户端:
    1、客户端无SQL,只是传递参数值。参数最好以强类型赋值。
    2、客户端的据集对象化,即实现简单的ORM功能。
    3、扩展现有的客户端的据集对象化,实现查询数据集体对象化。

    我还要仔细参悟大师的 SuperORM,delphi的RTTI没有.NET的反射机制强大,               很是苦恼。
    4、所有的TdataSet的中文标题通过数据库表自动填充实现,包括数据集字段的
              一些属性,比如 format格式,对其方式、默认值、Required等。
5、实体类的Lookup自动化,其实现原理获得所有表与表之间的关系,自动               实现数据集的Lookup,不需人工干预,使 Coding工作更高效,脱离码奴思想。
    6、一些常用的数据库界面控件封装。现在采用 Ehlib套件和 DevExpress的垂直表格控件。快速获得最强大最方便的前台功能界面。
    7、实体类也可以实现可视化界面设计,比如在TDataModule放置
               TDataSource, TAdoConnection ,TAdoQuery之类,如果需要可视化处理
               DataField和表格列宽,录入 SQL到 TAdoQuery。
               与此类推应用到BDE,DbExpress。切换数据集控件时候不要忘记无用的Uses单元名称。
            8、一个通用强大的查询对话框。可实现复杂的多表连接查询。
             
            服务端:
            1、服务端的AOP,即面向功能或面向服务。所有的方法或函数放在服务端上,
               且方法或函数为无参数形式,其内部参数通过对应的客户端输入参数获得。
服务端以动态组合方法或函数的方式执行任务。支持事务机制。
说起来,也没有MeAOP强大和专业了。
http://www.delphibox.com/article.asp?articleid=3309
http://dev.cq118.com/web/ow.asp?p=FrontPage


            2、客户端打开数据集或执行任务完毕,关闭数据库连接,节省资源。
            3、具体数据集无关性。即封装TdataSet或 TClientDataSet,即切换ADO或
               或BDE或DbExpress,将修改工作量减到最少。
            4、实现了界面与业务功能代码分离以后,再将改为三层结构,就容易多了。
你说是不是呢?

以上一些方法已经实现或陆续实现,但未认真整理过。
如果你修改了源码或有好的想法,如果方便请你也告诉我。毕竟,有交流才有进步。

posted on 2009-11-10 00:31  网语飘飘  阅读(356)  评论(0)    收藏  举报