2017-07-20 2 views
0

Hat jemand Erfahrung mit SQL Server RowVersion Spalte mit TClientDataset? Genauer gesagt muss ich den RowVersion Wert auf Einfügen zurückgeben. Es scheint, den RowVersion Wert wieder auf Updates zu bekommen, aber eine neu eingefügte Zeile tut es nicht.Delphi TClientDataset SQL Server RowVersion

Antwort

3

Dies scheint ein ähnliches Problem einzubinden, wenn Sie eine CDS mit einer SqlServer Tabelle verwenden müssen, die ein Identitätsfeld hat, wobei der Wert in dem Feld durch den Server eingestellt ist, so dass Sie wissen, dass es nicht während der CDS-Seite einfügen Operation. Ein Weg, dies zu tun, wird in diesem Artikel http://edn.embarcadero.com/article/20847 erklärt. Es geht um einen temporären, negativen, Wert auf das Identity-Feld in den CDS im OnNewRecord Ereignisse zuweisen, und dann mit der Refresh Methode der CDS auf rufen Sie den serverseitige Identität Feldwert, sobald der neue Rekord wurde veröffentlicht zum Server durch den Aufruf ApplyUpdates.

In D7, die ich für diese Antwort als eine Art kleinsten gemeinsamen Nenner verwenden, scheint diese Technik gut zu einem RowVersion-Feld zu funktionieren. Ein Auszug aus einem Beispielprojekt ist unten. Um es funktioniert, hatte ich das RowVersion Feld als ftBytes Feld mit einer Größe von 8 zu definieren und die ProviderFlags zu ändern pfInWhere und pfInUpdate vom AdoQuery Identität Feld, ID auszuschließen.

Das Feld RowVerStr im CDS dient nur dazu, den Wert lesbar in einem TDBGrid anzuzeigen.

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' ist ein [Synonym (tatsächlich Ersatz) für' timestamp'] (https://docs.microsoft.com/en-us/sql/t-sql/data-types/rowversion-transact -sql). – Victoria

+0

@avidgolfer: Hat das dein Problem gelöst? – MartynA

+0

@MartynA: Ihre Lösung funktioniert. Scheint übermäßig gesprächig, aber ich bin nicht in der Lage, es in meiner Umgebung zu implementieren, aufgrund von Beschränkungen, die außerhalb meiner Kontrolle liegen. – avidgoffer

Verwandte Themen