2017-07-20 6 views
0

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

3

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; 
+0

'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

+0

@avidgolfer: cela a-t-il résolu votre problème? – MartynA

+0

@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