Delphi TClientDataset SQL 服务器行版本
Delphi TClientDataset SQL Server RowVersion
有没有人有使用 SQL Server 的 RowVersion
列和 TClientDataset
的经验?具体来说,我需要在插入时取回 RowVersion
值。它似乎在更新时恢复了 RowVersion
值,但新插入的行却没有。
这似乎涉及到与您需要使用 CDS 时类似的问题
一个 SqlServer table,它有一个 Identity 字段,其中字段中的值
由服务器设置,因此在 CDS 端插入操作期间您不知道它。本文解释了一种方法
http://edn.embarcadero.com/article/20847。它涉及
为 CDS 中的 Identity 字段分配一个临时的负值
在 OnNewRecord
事件中,然后使用 CDS 的 Refresh
方法来
新记录完成后检索服务器端身份字段值
通过调用 ApplyUpdates
.
发布到服务器
在 D7 中,我将其用作此答案的一种最小公分母,
这种技术似乎也适用于 RowVersion 字段。一个
下面是示例项目的摘录。为了让它工作,我必须定义
将 RowVersion 字段作为大小为 8 的 ftBytes
字段,并更改
ProviderFlags
从中排除 pfInWhere
和 pfInUpdate
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;
有没有人有使用 SQL Server 的 RowVersion
列和 TClientDataset
的经验?具体来说,我需要在插入时取回 RowVersion
值。它似乎在更新时恢复了 RowVersion
值,但新插入的行却没有。
这似乎涉及到与您需要使用 CDS 时类似的问题
一个 SqlServer table,它有一个 Identity 字段,其中字段中的值
由服务器设置,因此在 CDS 端插入操作期间您不知道它。本文解释了一种方法
http://edn.embarcadero.com/article/20847。它涉及
为 CDS 中的 Identity 字段分配一个临时的负值
在 OnNewRecord
事件中,然后使用 CDS 的 Refresh
方法来
新记录完成后检索服务器端身份字段值
通过调用 ApplyUpdates
.
在 D7 中,我将其用作此答案的一种最小公分母,
这种技术似乎也适用于 RowVersion 字段。一个
下面是示例项目的摘录。为了让它工作,我必须定义
将 RowVersion 字段作为大小为 8 的 ftBytes
字段,并更改
ProviderFlags
从中排除 pfInWhere
和 pfInUpdate
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;