【问题标题】:Delphi TClientDataset SQL Server RowVersionDelphi TClientDataset SQL Server RowVersion
【发布时间】:2017-07-20 20:32:40
【问题描述】:

有没有人有使用 SQL Server 的 RowVersion 列和 TClientDataset 的经验?具体来说,我需要在插入时重新获取 RowVersion 值。似乎在更新时恢复了 RowVersion 值,但新插入的行却没有。

【问题讨论】:

    标签: sql-server delphi tclientdataset rowversion


    【解决方案1】:

    这似乎涉及到与您需要使用 CDS 时类似的问题 具有 Identity 字段的 SqlServer 表,其中字段中的值 是服务器设置的,所以在CDS端插入操作的时候是不知道的。本文解释了一种方法 http://edn.embarcadero.com/article/20847。它涉及 为 CDS 中的 Identity 字段分配一个临时的负值 在OnNewRecord事件中,然后使用CDS的Refresh方法来 获取新记录后检索服务器端标识字段值 通过调用ApplyUpdates发布到服务器。

    在 D7 中,我将此答案用作一种最低公分母, 这种技术似乎也适用于 RowVersion 字段。一个 示例项目的摘录如下。为了让它工作,我必须定义 RowVersion 字段作为 ftBytes 字段,大小为 8,并更改 ProviderFlags 排除 pfInWherepfInUpdate 从 AdoQuery 的身份字段,ID。

    CDS 中的RowVerStr 字段只是为了在 TDBGrid 中清晰地显示值。

    type
      TForm1 = class(TForm)
        ADOConnection1: TADOConnection;
        ADOQuery1: TADOQuery;
        DataSetProvider1: TDataSetProvider;
        DataSource1: TDataSource;
        DBGrid1: TDBGrid;
        DBNavigator1: TDBNavigator;
        ADOQuery1ID: TAutoIncField;  //  The ID field is an Identity field on the server
        ADOQuery1IntValue: TIntegerField;  //  a user field
        CDS1: TClientDataSet;
        CDS1ID: TAutoIncField;
        CDS1IntValue: TIntegerField;
        CDS1RowVersion: TBytesField;
        CDS1RowVerStr: TStringField;  //  just for display, fkInternalCalc, size = 20
        ADOQuery1RowVersion: TBytesField;
        procedure FormCreate(Sender: TObject);
        procedure CDS1AfterPost(DataSet: TDataSet);
        procedure CDS1AfterDelete(DataSet: TDataSet);
        procedure CDS1NewRecord(DataSet: TDataSet);
        procedure CDS1AfterInsert(DataSet: TDataSet);
        procedure CDS1CalcFields(DataSet: TDataSet);
      public
        FID : Integer;  //  To generate temporary value for CDS identity field
        function NextID : Integer;
      end;
    
    [...]
    
    function GetRowVerString(V : Variant) : String;
    var
      i,
      Dim,
      Min,
      Max : Integer;
      i64 : Int64;
    begin
      Result := '';
      if not VarIsArray(V) then Exit;
      Dim := VarArrayDimCount(V);
      Max := VarArrayHighBound(V, Dim);
      Min := VarArrayLowBound(V, Dim);
    
      for i := 0 to 7 do
        Int64Rec(i64).Bytes[i] := V[i];
      Result := IntToStr(i64);
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      //  CDS1ID is an ftAutoInc field, so we need to remove its read-only flag so
      //  that we can assign it a temporary negative value in the OnNewRecord event
      CDS1ID.ReadOnly := False;
    
      AdoQuery1RowVersion.ProviderFlags := AdoQuery1RowVersion.ProviderFlags - [pfInWhere, pfInUpdate];
    
      CDS1.Open;
      Caption := IntToStr(CDS1.RecordCount);
    end;
    
    procedure TForm1.CDS1AfterPost(DataSet: TDataSet);
    begin
      if CDS1.ApplyUpdates(0) = 0 then
        CDS1.Refresh;
    end;
    
    procedure TForm1.CDS1AfterDelete(DataSet: TDataSet);
    begin
      CDS1.ApplyUpdates(-1);
    end;
    
    function TForm1.NextID: Integer;
    begin
      Dec(FID);
      Result := FID;
    end;
    
    procedure TForm1.CDS1NewRecord(DataSet: TDataSet);
    begin
      CDS1.FieldByName('ID').AsInteger := NextID;
      CDS1.FieldByName('IntValue').AsInteger := Random(100);
    end;
    
    procedure TForm1.CDS1AfterInsert(DataSet: TDataSet);
    begin
      CDS1.Post;
    end;
    
    procedure TForm1.CDS1CalcFields(DataSet: TDataSet);
    begin
      CDS1RowVerStr.AsString := GetRowVerString(CDS1RowVersion.Value);
    end;
    

    【讨论】:

    猜你喜欢
    • 2011-05-27
    • 2020-06-12
    • 2012-11-20
    • 2012-04-20
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多