如何按指定顺序应用Delphi TClientDataset的更新?

如何按指定顺序应用Delphi TClientDataset的更新?,delphi,tclientdataset,Delphi,Tclientdataset,我需要按指定顺序应用更新(ClientDataSet.ApplyUpdate): -先删除 -修改为第二个 -作为第三个插入 它们是按完成的顺序应用的。请参阅KTDataComponents,了解如何实现这一点 除此之外,我有时通过切换到提供者端的OnUpdateData事件处理程序中的特定索引来形成所需的更新顺序。为了不破坏增量处理,必须使用两种技巧,但这是完全可行的 procedure TLogResolver.LogUpdateRecord(Tree: TUpdateTree); var

我需要按指定顺序应用更新(ClientDataSet.ApplyUpdate): -先删除 -修改为第二个 -作为第三个插入


它们是按完成的顺序应用的。

请参阅KTDataComponents,了解如何实现这一点

除此之外,我有时通过切换到提供者端的OnUpdateData事件处理程序中的特定索引来形成所需的更新顺序。为了不破坏增量处理,必须使用两种技巧,但这是完全可行的

procedure TLogResolver.LogUpdateRecord(Tree: TUpdateTree);
var
  I: Integer;
  CurVal: Variant;
  fld: TField;
  SaveRecNo: Integer;
  OldIndexName: WideString;
  OldIndexFieldNames: WideString;
begin
  if(TClientDataSet(Tree.Delta).IndexName<>'')or(TClientDataSet(Tree.Delta).IndexFieldNames<>'') then begin
    OldIndexName:=TClientDataSet(Tree.Delta).IndexName;
    OldIndexFieldNames:=TClientDataSet(Tree.Delta).IndexFieldNames;
    SaveRecNo:=Tree.Delta.RecNo;
    Tree.Delta.Edit;                       // vavan
    for I := 0 to Tree.Delta.FieldCount - 1 do begin
      fld:=Tree.Delta.Fields[I];
      { Blobs, Bytes and VarBytes are not included in result packet }
      if {(fld.IsBlob) or} (fld.DataType in [ftBytes, ftVarBytes]) then // vavan allowed blobs
        continue;
      CurVal := fld.NewValue;
      if not VarIsClear(CurVal) then begin
        fld.Value:=CurVal;  { TODO -ovavan -cSIC! : edit delta }
      end;
    end;
    Tree.Delta.Post; // vavan
    TClientDataSet(Tree.Delta).IndexName:=''; { TODO -ovavan -cSIC! : reset delta index to get correct original recno in order not to break reconcilation mechanism }
  end;
  try
    Tree.ErrorDS.IndexFieldNames:='ERROR_RECORDNO';
//    Tree.InitErrorPacket(nil, rrApply);
    TreeInitErrorPacket(Tree,nil, rrApply);
    for I := 0 to TVPacketDataSet(Tree.Delta).NewValueFields.Count - 1 do
    begin
      fld:=TVPacketDataSet(Tree.Delta).NewValueFields[i];
      { Blobs, Bytes and VarBytes are not included in result packet }
      if {(Tree.Delta.Fields[I].IsBlob) or} // vavan allowed blobs
         (fld.DataType in [ftBytes, ftVarBytes]) then
        continue;
      CurVal := fld.NewValue;
      if not VarIsClear(CurVal) then begin { TODO 2 -ovavan -ccheck! : get rid of this check since we only process modified fields? }
        Tree.ErrorDS.Fields[6+fld.Index].Value := CurVal; { TODO -ovavan -ccheck : ErrorDS fieldd structure is identical to delta but with extra 6 leading fields }
      end;
    end;
    Tree.ErrorDS.Post;
  finally
    if(OldIndexName<>'')then begin
      TClientDataSet(Tree.Delta).IndexName:=OldIndexName;
      Tree.Delta.RecNo:=SaveRecNo;
    end else
    if(OldIndexFieldNames<>'')then begin
      TClientDataSet(Tree.Delta).IndexFieldNames:=OldIndexFieldNames;
      Tree.Delta.RecNo:=SaveRecNo;
    end;
  end;
end;
过程TLogResolver.LogUpdateRecord(树:TUpdateTree);
变量
I:整数;
曲线型:变异型;
fld:TField;
SaveRecNo:整数;
OldIndexName:WideString;
OldIndexFieldNames:宽字符串;
开始
如果是(TClientDataSet(Tree.Delta).IndexName“”)或(TClientDataSet(Tree.Delta).indexFieldName“”),则开始
OldIndexName:=TClientDataSet(Tree.Delta).IndexName;
OldIndexFieldNames:=TClientDataSet(Tree.Delta);
SaveRecNo:=Tree.Delta.RecNo;
Tree.Delta.Edit;//vavan
对于I:=0到Tree.Delta.FieldCount-1,请开始
fld:=树的增量字段[I];
{结果数据包中不包括blob、Bytes和VarBytes}
如果{(fld.IsBlob)或}(fld.DataType在[ftBytes,ftVarBytes]中),那么//vavan允许的blob
继续;
曲线:=fld.NewValue;
如果不是VarIsClear(曲线),则开始
fld.值:=曲线;{TODO-ovavan-cSIC!:编辑增量}
结束;
结束;
Tree.Delta.Post;//vavan
TClientDataSet(Tree.Delta).IndexName:='';{TODO-ovavan-cSIC!:重置增量索引以获得正确的原始recno,以免破坏对账机制}
结束;
尝试
Tree.ErrorDS.indexFieldName:='ERROR\u RECORDNO';
//InitErrorPacket(nil,rrApply);
TreeInitErrorPacket(Tree,nil,rrApply);
对于I:=0到TVPacketDataSet(Tree.Delta).NewValueFields.Count-1 do
开始
fld:=TVPacketDataSet(Tree.Delta).NewValueFields[i];
{结果数据包中不包括blob、Bytes和VarBytes}
如果{(Tree.Delta.Fields[I].IsBlob)或}//vavan允许的blob
(fld.DataType输入[ftBytes,ftVarBytes]),然后
继续;
曲线:=fld.NewValue;
如果不是VarIsClear(CurVal),则开始{TODO 2-ovavan-ccheck!:取消此检查,因为我们只处理修改过的字段?}
Tree.errors.Fields[6+fld.Index]。值:=CurVal;{TODO-ovavan-ccheck:ErrorDS-fieldd结构与delta相同,但有额外的6个前导字段}
结束;
结束;
Tree.errors.Post;
最后
如果为(OldIndexName“”),则开始
TClientDataSet(Tree.Delta).IndexName:=OldIndexName;
Tree.Delta.RecNo:=SaveRecNo;
结束其他
如果为(OldIndexFieldNames“”),则开始
TClientDataSet(Tree.Delta).IndexFieldNames:=OldIndexFieldNames;
Tree.Delta.RecNo:=SaveRecNo;
结束;
结束;
结束;

AFAIK没有办法处理这个问题,我也不知道原因是什么,我使用缓存更新。数据库中可能存在一些约束(例如,记录或唯一索引的有效性重叠),如果用户插入记录,而不是编辑或删除另一条记录,则最终结果集可能是正确的,但无法应用。例如:我在数据库中有一个唯一键为1,VAL=A的记录。我插入一个键为1,值为VAL=B的记录,并删除键为1,VAL=A的记录。这在默认顺序中失败,但在删除、修改、插入顺序中成功。是的,这将失败,因为您按错误的顺序执行,并且这将导致错误的数据(有两行,主键相同)-可能只是一秒钟,但错误就是错误,不管我知道多久是的。但是数据是由用户修改的-这就是为什么我需要对操作进行重新排序以删除、修改、插入来解决它。我非常确定所有数据操作都由应用程序控制。因此,您可以抛出异常或简单地更新记录,而不是追加/delete你能说得更具体一点吗?如果我更改了onUpdate数据中的索引,那么它的顺序是正确的,但行为是错误的-我认为这是因为delta数据集包含多行用于编辑(第一行是原始行,第二行是更改的字段)。如果我更改订单,我会陷入混乱。根据您的要求,您可以创建仅用于更新排序的额外字段。然后,在OnUpdate Data(或CD端)中,您可以根据所需的顺序进行填充,在更新时保持新旧记录“成对”如果我保留“成对”的顺序记录它第一次工作正常。但如果第一次ApplyUpdate失败,并且用户在下一次ApplyUpdate中再次修改数据,则会出现错误-数据有问题,可能是由于数据集行顺序更改。我找不到问题所在:(是的,每当新值被修改以传播回CD或在应用更新期间发生错误时,都需要临时重置增量索引,以避免破坏对账逻辑。我个人在自己的自定义解决方案中的LogUpdateRecord/LogUpdateError中这样做。有一些很好的方法可以将增量索引重置为原始顺序吗?如果我暗示清除索引属性没有帮助。所以现在我使用两个字段,一个用于原始顺序,另一个用于我的顺序。但它不是那么优雅。