TxDataWebDataset / ID AutoInc

Hello all,

I use TxDataWebdataset to Post new record to a XData WebServer.
I post the new records with ID -1 and the DB-trigger creates the "real" ID then.
That works fine and is clear to me.

For the same ID I need to send BLOB content like RTF or other Blob Data.

So currently I reload the list of records and another form must be opened to upload the BLOB-content.
So I have the ID and the Blob-content and can upload that to the xData-Server.

While this works in general - it does not seem very clever and smart to me.

Is there a way I can get this last inserted "real" ID of the database when ApplyUpdates is called without reloading data? I need this ID to upload the blob-data to the server ?
Or is there a way to post the Blob-data "together" with the xDataWebDataset ?
Or do I need to create a Service on the Server to achieve this ?

I guess this is a common scenario that the server sets the real ID - and since everything is stateless one does not know this new ID.
How do you deal with that or do you use a complete different approach ?

Thanks/Regards, Tom

You can use the following code in AfterApplyUpdates event handler to update the ids of returned objects:

procedure TForm1.XDataWebDataset1AfterApplyUpdates(Sender: TDataSet; Info: TResolveResults);
var
  I: integer;
  BM: TBookmark;
begin
  BM := XDataWebDataset1.GetBookmark;
  try
    for I := 0 to Length(Info.Records) do
    begin
      XDataWebDataset1.GotoBookmark(Info.Records[I].BookMark);
      TJSObject(XDataWebDataset1.CurrentData)['Id'] := TJSObject(Info.Records[I].Data)['Id'];
    end;
  finally
    XDataWebDataset1.GotoBookmark(BM);
  end;
end;
1 Like

Hello Wagner,

I struggle with the Bookmark in your code. It compiles and I can run it in browser, but when I append new data I see this error
"Cannot read properties of undefined (reading 'BookMark') at Object.XDataWebDataSet1AfterApplyUpdates" in my browser-console.

Do I need to add a special unit to make this bookmark work ? From what I see there is a difference between TDataset.Bookmark and XData.Web.JsonDataset.Bookmark.

Thanks, Tom

I send you the code with a small issue, maybe that's the reason. The for loop is wrong:

    for I := 0 to Length(Info.Records) - 1 do

Hello Wagner,

the code works fine now - thanks - I get this response-header...
Anforderungsmethode: POST
Statuscode: 201 Created

But I still get the ID "-1" back as JSON Payload of the answer.
{
"$id": 1,
"ID": -1,
"TITEL": "New 16:40:52"
}
Although the record was created with ID 35 in the DB !

Any ideas ?

Thanks, Tom

Do you have a project reproducing the issue? The ID should come filled in the JSON response.

Hi Wagner,

maybe/hopefully I will find the mistake I made here when I create such a project...
Otherwise I will send it.

Regards, Tom

Hello Wagner,

attached find a project showing that behaviour. Since it's the first time I needed to upload a project for support I'm not quite sure if I added/left the right files.
xData_SimpleDB.zip (1.2 MB)

Get back to me in case something is missing.

Regards, Tom

Well, you are inserting the record with ID = -1:

procedure TForm1.btnAppendNewDataClick(Sender: TObject);
begin
  XDataWebDataSet1.Append;
  XDataWebDataSet1.Fields[0].AsInteger := -1;
  XDataWebDataSet1.Fields[1].AsString := 'New '+TimeToStr(Now);
  XDataWebDataSet1.Post;
end;

And since your generator is none:

  
  [Entity]
  [Table('SIMPLETABLE')]
  [Id('FID', TIdGenerator.None)]
  TSIMPLETABLE = class

It will simply save with the value you provided. So all is correct.
If you change your entity to automatically generate an id:

  [Entity]
  [Table('SIMPLETABLE')]
  [Id('FID', TIdGenerator.IdentityOrSequence)]
  TSIMPLETABLE = class

And do not set the ID client side:

procedure TForm1.btnAppendNewDataClick(Sender: TObject);
begin
  XDataWebDataSet1.Append;
  XDataWebDataSet1.Fields[1].AsString := 'New '+TimeToStr(Now);
  XDataWebDataSet1.Post;
end;

It should work as you expect.

Hello Wagner,

when doing exactly what you proposed I get "AutoGeneratedValuesNotSupported" from server.
Please mind: On Server there is a Trigger Before Insert, that creates this new ID by using a Generator when null or <1. Not sure how xDataServer and WebClientDataset deals with that...

How would you configure this ID-Field on FireBird DB ? I've simply used an Integer /Primary Key with the generator - I think this is common use...

Regards, Tom

It's common use, but then you have to tell Aurelius what is the generator you want to use, using the Sequence attribute. Then you can disable the trigger or at least adapt it to not touch the ID if it was passed via Insert.

It's Aurelius which will get the new id from generator and set it in the INSERT statement.

Hello Wagner,

thanks - this works perfectly fine now. Here find the working project
xData_SimpleDB_neo.zip (41.5 KB)

Regards, Tom

1 Like

This topic was automatically closed 60 minutes after the last reply. New replies are no longer allowed.