zoukankan      html  css  js  c++  java
  • TClientDataSet[9]: 计算字段和 State

    TClientDataSet 中计算字段有两种: Calculated(计算字段)、InternalCalc(内部计算字段).

    两者区别是: Calculated 在每次需要时都要重新计算; InternalCalc 只需要计算一次.
    Calculated 需要计算的时间, InternalCalc 需要存取的时间; 当然后者快.

    计算字段不会被保存到文件.



    下面的例子先定义了两个整数字段: sum1、sum2;
    又定义了两个计算字段: SUM(求和)、MUL(求积), 分别指定了 Calculated、InternalCalc.

    计算是在 TClientDataSet 的 OnCalcFields 事件中完成的, 每当需要计算结果时事件会被自动激活.
    除了 OnCalcFields 事件中的代码外, 其他都可以在设计时完成; 这里是动态完成的.


    //准备: 窗体放置 ClientDataSet1、DataSource1、DBGrid1(关联一下)、Button1
    //程序运行后, 可用 Tab 和 ↑ ↓ → ← 键配合着输入测试数据.
    
    { 建立数据集, 包括计算字段 }
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      with TIntegerField.Create(Self) do
      begin
        FieldName := 'num1';       { FieldKind 的默认值是 fkData }
        DataSet := ClientDataSet1;
      end;
    
      with TIntegerField.Create(Self) do
      begin
        FieldName := 'num2';
        DataSet := ClientDataSet1;
      end;
    
      with TIntegerField.Create(Self) do
      begin
        FieldName := 'SUM';
        FieldKind := fkCalculated;  { 指定为计算字段 }
        DataSet := ClientDataSet1;
      end;
    
      with TIntegerField.Create(Self) do
      begin
        FieldName := 'MUL';
        FieldKind := fkInternalCalc; { 指定为内部计算字段 }
        DataSet := ClientDataSet1;
      end;
    
      ClientDataSet1.CreateDataSet;
      Button1.Enabled := False;
    end;
    
    { OnCalcFields 事件 }
    procedure TForm1.ClientDataSet1CalcFields(DataSet: TDataSet);
    begin
      { 获取计算字段的值 }
      DataSet['SUM'] := DataSet['num1'] + DataSet['num2'];
    
      { 获取内部计算字段的值; 一般要先判断一下以避免重复运算 }
      if DataSet.State = dsInternalCalc then
        DataSet['MUL'] := DataSet['num1'] * DataSet['num2'];
    end;


    在上面程序的基础上再添加一个 Timer1, 为详细测试 Calculated 和 InternalCalc 的区别, 代码修改如下:


    var
      Calc, InternalCalc: Integer;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      i: Integer;
    begin
      with TIntegerField.Create(Self) do
      begin
        FieldName := 'num1';
        DataSet := ClientDataSet1;
      end;
    
      with TIntegerField.Create(Self) do
      begin
        FieldName := 'num2';
        DataSet := ClientDataSet1;
      end;
    
      with TIntegerField.Create(Self) do
      begin
        FieldName := 'SUM';
        FieldKind := fkCalculated;
        DataSet := ClientDataSet1;
      end;
    
      with TIntegerField.Create(Self) do
      begin
        FieldName := 'MUL';
        FieldKind := fkInternalCalc; { 指定为内部计算字段 }
        DataSet := ClientDataSet1;
      end;
      ClientDataSet1.CreateDataSet;
    
      { 添加测试数据 }
      ClientDataSet1.DisableControls;
      for i := 0 to 999 do ClientDataSet1.AppendRecord([i, i]);
      ClientDataSet1.EnableControls;
    
      Button1.Enabled := False;
    end;
    
    procedure TForm1.ClientDataSet1CalcFields(DataSet: TDataSet);
    begin
      Inc(Calc);
      DataSet['SUM'] := DataSet['num1'] + DataSet['num2'];
    
      if DataSet.State = dsInternalCalc then
      begin
        Inc(InternalCalc);
        DataSet['MUL'] := DataSet['num1'] * DataSet['num2'];
      end;
    end;
    
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      Text := Format('Calc: %d; InternalCalc: %d', [Calc, InternalCalc]);
    end;


    测试图:



    TDataSetState.State: TDataSetState;
    TDataSetState = (
    dsInactive,     { 数据集被关闭 }
    dsBrowse,       { 浏览模式 }
    dsEdit,         { 编辑模式, 意味着 Edit 方法已被调用, 而编辑后的数据尚未被提交 }
    dsInsert,       { 插入模式, 即 insert 被调用, 但变化还没有提交 }
    dsSetKey,       { 设置键值模式, 意味着 SetKey 被调用, 而 GotoKey 尚未被调用 }
    dsCalcFields,   { OnCalcFields 事件已发生, 对记录值的计算正在进行中 }
    dsFilter,       { 数据集正在处理一个记录过滤器、查找字段或其他需要用到过滤器的操作 }
    dsNewValue,     { 数据集处于 NewValue 属性被访问的临时状态 }
    dsOldValue,     { 数据集处于 OldValue 属性被访问的临时状态 }
    dsCurValue,     { 数据集处于 CurValue 属性被访问的临时状态 }
    dsBlockRead,    { 数据正被写入缓冲区, 此时数据库表中指针的移动并不触发数据感知组件的更新和事件的发生 }
    dsInternalCalc, { 一个字段值正在被计算, 以供一个有 fkInterternalCalc 类型的 Fieldkind 属性的字段使用 }
    dsOpening       { 数据集处于正在打开状态但是还没有结束, 这种状态发生在数据集被异步打开时 }
    );

     
  • 相关阅读:
    Java学习二十九天
    Java学习二十八天
    47. Permutations II 全排列可重复版本
    46. Permutations 全排列,无重复
    subset ii 子集 有重复元素
    339. Nested List Weight Sum 339.嵌套列表权重总和
    251. Flatten 2D Vector 平铺二维矩阵
    217. Contains Duplicate数组重复元素
    209. Minimum Size Subarray Sum 结果大于等于目标的最小长度数组
    438. Find All Anagrams in a String 查找字符串中的所有Anagrams
  • 原文地址:https://www.cnblogs.com/jijm123/p/13976697.html
Copyright © 2011-2022 走看看