Delphi TClientDataset SQL Server RowVersion

У кого-нибудь есть опыт использования столбца RowVersion SQL Server с TClientDataset? В частности, мне нужно вернуть значение RowVersion при вставке. Кажется, что значение RowVersion возвращается при обновлениях, но только что вставленная строка - нет.


person avidgoffer    schedule 20.07.2017    source источник


Ответы (1)


Это похоже на проблему, аналогичную ситуации, когда вам нужно использовать CDS с таблицей SqlServer, которая имеет поле Identity, где значение в поле устанавливается сервером, поэтому вы не знаете его во время вставки на стороне CDS. операция. Один из способов сделать это объясняется в этой статье http://edn.embarcadero.com/article/20847< /а>. Он включает в себя присвоение временного отрицательного значения полю Identity в CDS в событии OnNewRecord, а затем использование метода Refresh CDS для извлечения значения поля идентификатора на стороне сервера после того, как новая запись была отправлена ​​на сервер звоню ApplyUpdates.

В D7, который я использую для этого ответа как своего рода наименьший общий знаменатель, этот метод, похоже, отлично работает и с полем RowVersion. Выдержка из примера проекта приведена ниже. Чтобы заставить его работать, мне пришлось определить поле RowVersion как поле ftBytes с размером 8 и изменить ProviderFlags, чтобы исключить pfInWhere и pfInUpdate из поля идентификатора AdoQuery, ID.

Поле RowVerStr в CDS предназначено только для разборчивого отображения значения в 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;
person MartynA    schedule 21.07.2017
comment
@MartynA: ваше решение работает. Кажется чрезмерно болтливым, но я не могу реализовать его в своей среде из-за ограничений, наложенных на меня вне моего контроля. - person avidgoffer; 27.07.2017