Datasnap\FireDAC: Query executed twice

885 views Asked by At

I have the following problem:

1) I use Delphi XE7 to develop a 3-layer system.

2) The server layer, created with datasnap using REST.

3) I use Firebird as database and the access is performed with FireDAC.

4) I have a sequence with value 01.

5) I created the following query in the server layer:

Select GEN_ID (gen_my_sequence, 1) from rdb $ database

6) On the server returns the sequence value in the query is: 02.

7) But the client layer returns 03.

I do not understand why the query is executed twice.

Can anyone help me?

2

There are 2 answers

2
Luiz On BEST ANSWER

I use technical standards that the Embarcadero indicates.

What I realized was this:

1) The unit Data.FireDACJSONReflect in TFDJSONInterceptor.ItemListToJSONObject routine has this block of code:

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;

See he activates the query once, causing the sequence to be incremented.

But in DataSetToJSONValue (LDataSet) routine; This code block is:

if  (LMemTable = nil) then
    begin
    LMemTable := TFDMemTable.Create(nil);
    LAdapter := TFDTableAdapter.Create(nil);
    LMemTable.Adapter := LAdapter;
    LAdapter.SelectCommand := ADataSet.Command;
    LMemTable.Active := True;
    end;

See he again activates the query, where the sequence is again incremented.

Now I do not know if I made a mistake or if it is a bug, but I created a new class inherited from TFDMemTable and thought there was some mistake in this class, but did a test with TFDMemTable component, standard component of FireDAC, and even then the activation of any query is performed twice, because the code does not consider any of these two classes, as a TFDCustomMemTable, even though they were inherited directly from this class.

I commented the code of DataSetToString routine (const ADataSet: TFDAdaptedDataSet) that looked like this:

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;}

In this way the problem was solved, and the performance of the application seemed to have improved.

5
Sotirca Mihaita George On

This is the nature of generators (sequences) in firebird. Their value is increased every time you request it and the value of the generator is updated from that request and remains updated. Also generators live outside of transaction control. See this firebirdsql generatorguide-basics. It doesn't matter where you request it from.