Est-ce que quelqu'un a déjà utilisé la colonne RowVersion
de SQL Server avec TClientDataset
? Plus précisément, je dois récupérer la valeur RowVersion
sur l'insertion. Il semble obtenir la valeur RowVersion
sur les mises à jour, mais une ligne nouvellement insérée ne le fait pas.Delphi TClientDataset SQL Server RowVersion
Répondre
Cela semble impliquer un problème similaire lorsque vous devez utiliser un CDS avec une table de SqlServer qui a un champ d'identité, où la valeur dans le champ est défini par le serveur, de sorte que vous ne savez pas pendant l'opération d'insertion côté CDS. Une façon de le faire est expliquée dans cet article http://edn.embarcadero.com/article/20847. Elle implique attribuer une valeur temporaire, négative, au champ d'identité dans les CDS en cas OnNewRecord
, puis en utilisant la méthode Refresh
des CDS à récupérer le champ d'identité côté serveur valeur une fois que le nouveau record a été posté au serveur en appelant ApplyUpdates
.
Dans D7, que j'utilise pour cette réponse comme une sorte de plus petit dénominateur commun, cette technique semble également fonctionner correctement dans un champ RowVersion. Un extrait d'un projet exemple est ci-dessous. Pour le faire fonctionner, je devais définir le champ RowVersion comme un champ ftBytes
avec une taille de 8 et de changer le ProviderFlags
d'exclure pfInWhere
et pfInUpdate
du champ d'identité de AdoQuery, ID.
Le champ RowVerStr
dans le CDS est juste pour afficher la valeur lisiblement dans un 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;
'rowversion' est un [synonyme (en fait le remplacement) pour' timestamp'] (https://docs.microsoft.com/en-us/sql/t-sql/data-types/rowversion-transact -sql). – Victoria
@avidgolfer: cela a-t-il résolu votre problème? – MartynA
@MartynA: votre solution fonctionne. Cela semble excessivement bavard, mais je ne suis pas capable de l'implémenter dans mon environnement en raison des restrictions qui m'incombent. – avidgoffer