Search code examples
delphifirebirddatasnapfiredac

Datasnap\FireDAC: Query executed twice


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?


Solution

  • 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.