Datasnap\FireDAC: 查询执行了两次
Datasnap\FireDAC: Query executed twice
我有以下问题:
1) 我用DelphiXE7开发了一个3层系统
2) 服务器层,使用 REST 使用 datasnap 创建。
3) 我使用Firebird作为数据库,使用FireDAC进行访问。
4) 我有一个值为 01.
的序列
5) 我在服务器层创建了以下查询:
Select GEN_ID (gen_my_sequence, 1) from rdb $ database
6) 在服务器 returns 上,查询中的序列值为:02.
7)但是客户层returns03.
我不明白为什么查询执行了两次。
谁能帮帮我?
这就是 firebird 中生成器(序列)的本质。每次您请求时,它们的值都会增加,并且生成器的值会根据该请求更新并保持更新。生成器也存在于事务控制之外。
看到这个 firebirdsql generatorguide-basics。无论您从哪里请求它都没有关系。
我使用 Embarcadero 指示的技术标准。
我意识到的是:
1) Data.FireDACJSONReflect单元在TFDJSONInterceptor.ItemListToJSONObject例程中有这段代码:
if not LActive then
LDataSet.Active := True;
try
LJSONDataSet := DataSetToJSONValue(LDataSet);
// Use AddPair overload that will accept blank key
AJSONObject.AddPair(TJSONPair.Create(LPair.Key, LJSONDataSet))
finally
if not LActive then
LDataSet.Active := False;
end;
看到他激活了一次查询,导致序列递增。
但在DataSetToJSONValue(LDataSet)例程中;此代码块是:
if (LMemTable = nil) then
begin
LMemTable := TFDMemTable.Create(nil);
LAdapter := TFDTableAdapter.Create(nil);
LMemTable.Adapter := LAdapter;
LAdapter.SelectCommand := ADataSet.Command;
LMemTable.Active := True;
end;
看到他再次激活查询,其中序列再次递增。
现在我不知道是我弄错了还是bug,但是我创建了一个新的class继承自TFDMemTable并且认为有一些class 中的错误,但使用 TFDMemTable 组件(FireDAC 的标准组件)进行了测试,即使如此,任何查询的激活都会执行两次,因为代码没有考虑这两个 class 中的任何一个,作为 TFDCustomMemTable,即使它们直接继承自此 class.
我评论了 DataSetToString 例程 (const ADataSet: TFDAdaptedDataSet) 的代码,如下所示:
LMemTable := nil;
LAdapter := nil;
try
//if (ADataSet is TFDCustomMemTable) then
LMemTable := TFDCustomMemTable(ADataSet);
{if (LMemTable = nil) then
begin
LMemTable := TFDMemTable.Create(nil);
LAdapter := TFDTableAdapter.Create(nil);
LMemTable.Adapter := LAdapter;
LAdapter.SelectCommand := ADataSet.Command;
LMemTable.Active := True;
end;}
这样问题就解决了,应用的性能似乎也有所提升。
我有以下问题:
1) 我用DelphiXE7开发了一个3层系统
2) 服务器层,使用 REST 使用 datasnap 创建。
3) 我使用Firebird作为数据库,使用FireDAC进行访问。
4) 我有一个值为 01.
的序列5) 我在服务器层创建了以下查询:
Select GEN_ID (gen_my_sequence, 1) from rdb $ database
6) 在服务器 returns 上,查询中的序列值为:02.
7)但是客户层returns03.
我不明白为什么查询执行了两次。
谁能帮帮我?
这就是 firebird 中生成器(序列)的本质。每次您请求时,它们的值都会增加,并且生成器的值会根据该请求更新并保持更新。生成器也存在于事务控制之外。 看到这个 firebirdsql generatorguide-basics。无论您从哪里请求它都没有关系。
我使用 Embarcadero 指示的技术标准。
我意识到的是:
1) Data.FireDACJSONReflect单元在TFDJSONInterceptor.ItemListToJSONObject例程中有这段代码:
if not LActive then
LDataSet.Active := True;
try
LJSONDataSet := DataSetToJSONValue(LDataSet);
// Use AddPair overload that will accept blank key
AJSONObject.AddPair(TJSONPair.Create(LPair.Key, LJSONDataSet))
finally
if not LActive then
LDataSet.Active := False;
end;
看到他激活了一次查询,导致序列递增。
但在DataSetToJSONValue(LDataSet)例程中;此代码块是:
if (LMemTable = nil) then
begin
LMemTable := TFDMemTable.Create(nil);
LAdapter := TFDTableAdapter.Create(nil);
LMemTable.Adapter := LAdapter;
LAdapter.SelectCommand := ADataSet.Command;
LMemTable.Active := True;
end;
看到他再次激活查询,其中序列再次递增。
现在我不知道是我弄错了还是bug,但是我创建了一个新的class继承自TFDMemTable并且认为有一些class 中的错误,但使用 TFDMemTable 组件(FireDAC 的标准组件)进行了测试,即使如此,任何查询的激活都会执行两次,因为代码没有考虑这两个 class 中的任何一个,作为 TFDCustomMemTable,即使它们直接继承自此 class.
我评论了 DataSetToString 例程 (const ADataSet: TFDAdaptedDataSet) 的代码,如下所示:
LMemTable := nil;
LAdapter := nil;
try
//if (ADataSet is TFDCustomMemTable) then
LMemTable := TFDCustomMemTable(ADataSet);
{if (LMemTable = nil) then
begin
LMemTable := TFDMemTable.Create(nil);
LAdapter := TFDTableAdapter.Create(nil);
LMemTable.Adapter := LAdapter;
LAdapter.SelectCommand := ADataSet.Command;
LMemTable.Active := True;
end;}
这样问题就解决了,应用的性能似乎也有所提升。