韩小明@xiammy的专栏

没水的地方挖井,有水的地方修渠

用户操作
[即时聊天] [发私信] [加为好友]
韩小明ID:xiammy
449775次访问,排名105好友15人,关注者83
毕业后一直在广联达工作
xiammy的文章
原创 178 篇
翻译 0 篇
转载 22 篇
评论 1134 篇
韩小明的公告
作者毕业于浙江大学,非常热爱体育运动。现在尤其热爱羽毛球运动。在休息时间非常热爱技术文章写作。
最近垃圾评论泛滥,为了不污染大家的视听,暂时关闭评论,请大家理解。
欢迎转载,但请注意,除非特别声明,本站采用Creative Commons License许可:署名,非商业。

最近评论
Norse:从纯逻辑的角度而言,只要加上一个条件就可以严谨地解决问题:此题是可解的。
这样的话顶多从半真是真还是假来加一层推理,易知半真是真的情况下是无解的,所以半真只能是假,最后就可以按标准答案推出结果了。
Norse:太钻牛角尖了,既然题目这么出,那就是隐含字条真假对应对金块判断的正误,而不是独立的
thesameway:51旧书网 同城易书
www.51jiushu.com
www.51jiushu.net
二手书、旧书同城交易平台
分类齐全、快速发布、准确搜索
xiammy:你说的就是推广策略,是不是采用矫枉过正?
sharkw:可以试一试SqliteSpy,支持sqlite数据库的加解密
文章分类
收藏
    相册
    图书
    链接
    宗刚的专栏(RSS)
    快乐学习(RSS)
    陈亮亮的专栏(RSS)
    朋友
    张恂论 OO
    橘子懒懒的BLOG(RSS)
    言之有李(RSS)
    赵伟的小家
    存档
    订阅我的博客
    XML聚合  FeedSky

    原创 动态创建ClientDataSet的表定义收藏

    新一篇: 论面向事件设计(EOD)和面向对象设计(OOD) | 旧一篇: 有关TDataSet的研究

    前言

    很多人都在问,ClientDataSet如何才能在不连接数据库得情况下,用程序创建起来,并打开数据集。

    在研究了一下TClientDataSet数据集后,发现如果要让ClientDataSet打开的话(Open),必须满足三个条件中的一个:

    1. ProviderName属性赋值,即有数据源提供者。
    2. Data属性赋值。即从其它已经打开的数据集中获得表结构和数据。
    3. FileName赋值,即从本地文件获取数据和MetaData。

    这三个条件是TClientDataSet的Active属性的帮助中说的。思考一下,第一和第二基本被排除,我如果有了现成的数据集,还要创建干吗?第三个又不是那么容易,你哪知道文件的格式是什么呢?

    那到底该怎么做呢?

    失败的尝试

    突然想起TClientDataSet中支持InternalCalc(内部计算)字段。内部计算字段可以在设计期加进去,或者也可以在运行期动态加入。我们为了方便,就在设计期加入。见下图:

    可以通过双击控件(TClientDataSet)进入字段编辑器,然后右键选择“New Field”命令,得到如图所示的界面。填写Name,Type和FieldType。

    记住:FieldType一定要是“InternalCalc”。如此反复,你可以选择添加多个字段。

    打开!报错:“ProviderName”或Data没有赋值。

    这个方法不正确,既然要Data,我尝试着,从其它ClientDataSet的Data属性赋值上。得到结果是:自己新建的字段和数据源的字段都显示。

    我又进行了进一步的尝试:那就是让这个有着新建的字段和原有字段的ClientDataSet的Data赋值到另一个新的ClientDataSet上,却发现新建的字段没有进入。

    总得来说,这次尝试是失败的,不过有如下总结:

    1. 光靠新建内部计算字段是不可行的。
    2. 新建的计算字段不可以进入Data属性而被传递给第二个ClientDataSet。

    XML

    又是XML!ClientDataSet本就是断开连接的数据集控件,应此提供了将数据缓存到磁盘的功能SaveToFile(),其详细声明如下:

      procedure SaveToFile(const FileName: string = ''; Format: TDataPacketFormat = dfBinary);
    

    注意到其中的TDataPacketFormat。它是个枚举类型,全部的枚举值如下:

      TDataPacketFormat = (dfBinary, dfXML, dfXMLUTF8);
    

    大家可能注意到了,dfBinary和dfXMLUTF8都不是我们需要关心的,关心一下我们的dfXML格式。这是个让人兴奋的消息。有了XML,我们就可以查看ClientDataSet的MetaData的定义,而且更有了修改的可能!

    调用一下SaveToFile功能,注意保存格式为dfXML。打开文件,如下显示:

      <?xml version="1.0" standalone="yes" ?> 
    - <DATAPACKET Version="2.0">
    - <METADATA>
    - <FIELDS>
    -  <FIELD attrname="NormInfoID" fieldtype="i4">
        <PARAM Name="PROVFLAGS" Value="7" Type="i4" Roundtrip="True" /> 
       </FIELD>
       <FIELD attrname="Description" fieldtype="string.uni" WIDTH="160" /> 
       <FIELD attrname="NormInfoVal" fieldtype="string.uni" WIDTH="510" /> 
       <FIELD attrname="NewField" fieldtype="i4" /> 
       <FIELD attrname="Boolean" fieldtype="Boolean" /> 
       <FIELD attrname="Date" fieldtype="date" /> 
       <FIELD attrname="Time" fieldtype="time" /> 
      </FIELDS>
      <PARAMS DEFAULT_ORDER="1" PRIMARY_KEY="1" /> 
      </METADATA>
      <ROWDATA /> 
      </DATAPACKET>

    看这个全部的,比较混乱,先看一下结构:

      <?xml version="1.0" standalone="yes" ?> 
    - <DATAPACKET Version="2.0">
      + <METADATA>
        <ROWDATA /> 
      </DATAPACKET>

    这下比较清楚了:

    整个XML定义为一个DataPacket,DataPacket包括两个部分:MetaData和RowData。显然对我们来说,RowData可以忽视,到时候将RowData的节点清空就是。而MetaData呢?

    看看全部的XML格式,可以看出:MetaData包括Fields和Params。即字段和数据集参数。

    字段

    先重点考虑Fields。看一下Field节点的定义,大概可以看出一些:

    1. attrname是指FieldName
    2. fieldtype是指字段类型
    3. width是需要宽度的字段类型的参数
    4. 如果需要定义字段的属性,再加上<Param />节点

    下面我们来研究一下字段类型,我想这也是最主要的!其它属于高级用法。

    MSSQL Type fieldtype WIDHT SUBTYPE DECIMALS READONLY
    Binary bin.hex 50      
    Bit boolean        
    Char string 10 FixedChar    
    DateTime dateTime        
    Decimal fixed 18      
    Float r8        
    Image bin.hex   Binary    
    Int i4        
    Money fixed 19   4  
    nChar string.uni 20      
    nText bin.hex   Text    
    Numeric fixed 18      
    nVarChar string.uni 100      
    SmallDateTime dateTime        
    Real r8        
    SmallInt i2        
    SmallMoney fixed 10   4  
    Text bin.hex   Text    
    TimeStamp bin.hex 8     true
    tinyInt i2        
    UniqueIdentifier string 38 Guid    
    VarBinary bin.hex 50 Binary    
    VarChar string 50      

    见上表,这是我在SQLServer2000中,将所有类型的字段都用上,然后在ClientDataSet中得到的,类型对应关系。注意到有SubType属性,来帮助决定类型。其中没有值的单元格,表示该属性没有用到。宽度值中,除了UniqueIdentifier是38外,其余都是采用系统默认宽度。

    分析一下这一张表,可以得到如下一些特点:

    1. 后缀uni表示unicode,没有后缀,则表示是AnsiCode
    2. 后缀hex表示16进制
    3. i后的数字表示整数所占用的位数,默认为4位
    4. r8表示8位浮点数

    字段参数

    注意到某些字段的定义下有节点:

    <PARAM Name="PROVFLAGS" Value="7" Type="i4" Roundtrip="True" /> 
    

    先来解释一下“PROVFLAGS”,在Delphi的源码里查找可以发现其实就是对应着TField的属性ProviderFlags,那么7也就是好理解的了。

    看TProviderFlag和TProviderFlags的定义

      TProviderFlag = (pfInUpdate, pfInWhere, pfInKey, pfHidden);
      TProviderFlags = set of TProviderFlag;
    

    既然是集合,那么7很显然就是一个集合的整数表示:按顺序排的话,7其实就是表示结合[pfInUpdate, pfInWhere, pfInKey]。

    不过不知道为什么,查看TField的属性,pfInKey不在集合中。

    MetaData属性

    看看

      <PARAMS DEFAULT_ORDER="1" PRIMARY_KEY="1" /> 
    

    可以看出DEFAULT_ORDER和PRIMARY_KEY的意思,但是后面的值呢?研究之后,发现,它是主键或索引字段的Index。如果同时两个字段都是索引,那么它的格式是:"1 2",中间采用空格隔开。

    如何使用XML格式?

    好了,格式大概都知道了,现在问题是如何转载到ClientDataSet呢?

    文件是可以,但是显然不满足我们当初的需求,在查看一下接口定义,发现除了LoadFromFile还有LoadFromStream。查看一下源码,其实LoadFromFile就是调用了LoadFromStream。

    好了,只要我们创建了这样的XML流,就可以动态创建ClientDataSet了!

    至于如何创建XML流,不在此讨论了

    发表于 @ 2003年10月21日 00:07:00|评论(loading...)|编辑

    新一篇: 论面向事件设计(EOD)和面向对象设计(OOD) | 旧一篇: 有关TDataSet的研究

    评论

    #sirit 发表于2007-08-26 13:40:52  IP: 60.209.64.*
    1、fieldtype(字段类型)是 fixedFMT,这是什么类型的数据?

    2、<PARAM Name="PROVFLAGS" Value="7" Type="i4" Roundtrip="True" />
    怎么设置使这一句出现在field里面?
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © 韩小明