roAfterUpdate - how?

Discussion of open issues, suggestions and bugs regarding IBDAC (InterBase Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
Post Reply
malmedin
Posts: 22
Joined: Fri 26 Mar 2010 19:52

roAfterUpdate - how?

Post by malmedin » Wed 09 Sep 2020 09:43

I set
IBCQuery.RefreshOptions := [roAfterUpdate];
to refresh record after update.

I was expected that this code
IBCQuery.Edit;
IBCQuery.FieldByName(SomeField).AsInteger := 1;
IBCQuery.Post;
calls
IBCQuery.RefreshRecord
but, it doesn't.

Am I missing something?

ViktorV
Devart Team
Posts: 3168
Joined: Wed 30 Jul 2014 07:16

Re: roAfterUpdate - how?

Post by ViktorV » Fri 18 Sep 2020 15:18

When calling the RefreshRecord method, the query specified in the SQLRefresh property will be executed. If the SQLRefresh property is empty, IBDAC will automatically generate an SQL query when the RefreshRecord method is executed. If you manually set the SQLRefresh property to the required query, it will be executed when the RefreshRecord method is called.
When you execute the above code, the corresponding request is executed, you can verify this using the dbMonitor tool.
Note that you can use dbMonitor to find out what information is sent to the server, as well as when it is sent.

malmedin
Posts: 22
Joined: Fri 26 Mar 2010 19:52

Re: roAfterUpdate - how?

Post by malmedin » Fri 18 Sep 2020 18:24

I was aware of everything you said, so I created sample project from scratch and it worked! I compared it to the project where it doesn't work and found out that roAfterUpdate has no effect if DMLRefresh is set to true. Help has a note saying that RefreshOptions should be set to false when DMLRefresh is set to true to avoid rereading fields from server. It doesn't say anythig about RefreshOptions beeing disabled when DMLRefresh is set to true.

I consider it a bug because DMLRefresh is needed for getting field values set by trigger and RefreshOptions is needed for getting field values from joined tables.

Example

Tables

Code: Select all

CREATE TABLE PARENTS
(
  ID INTEGER NOT NULL,
  NAME VARCHAR(30)
);

CREATE TABLE CHILDREN
(
  ID INTEGER NOT NULL, // field value is set by trigger
  PARENTID INTEGER,
  NAME VARCHAR(30)
);
Query.SQL

Code: Select all

SELECT c.ID, c.NAME, c.PARENTID, p.NAME
FROM CHILDREN c
JOIN PARENTS p ON p.ID = c.PARENTID
Query.SQLRefresh

Code: Select all

SELECT c.ID, c.NAME, c.PARENTID, p.NAME
FROM CHILDREN c
JOIN PARENTS p ON p.ID = c.PARENTID
WHERE c.ID = :ID
After insert in table CHILDREN, DMLRefresh (if set to true) is used to get ID.
After edit (and insert too) RefreshRecord (if roAfterUpdate and roAfterInsert are set to true) is used to get p.NAME.

But, they don't work together.

ViktorV
Devart Team
Posts: 3168
Joined: Wed 30 Jul 2014 07:16

Re: roAfterUpdate - how?

Post by ViktorV » Tue 22 Sep 2020 14:38

This is the correct behavior for our components. When DMLRefresh is True the request you specified will not be executed: https://www.devart.com/ibdac/docs/devar ... efresh.htm
But you can manually run TIBCQuery.RefreshRecord method to solve your issue.

malmedin
Posts: 22
Joined: Fri 26 Mar 2010 19:52

Re: roAfterUpdate - how?

Post by malmedin » Wed 23 Sep 2020 10:46

ViktorV, thank you for the answer, but as you can see in the link you posted, it says
When DMLRefresh property is set to True, TCustomDADataSet.RefreshOptions should be set to False to avoid rereading fields' values from the server.
It is implied that both can be set to true.

Is it possible to make it function as described in help and let users decide whether they want "rereading fields' values from the server"?

ViktorV
Devart Team
Posts: 3168
Joined: Wed 30 Jul 2014 07:16

Re: roAfterUpdate - how?

Post by ViktorV » Fri 25 Sep 2020 11:16

No, these queries won't be executed if DMLRefresh is enabled. We'll make changes to our documentation to remove ambiguity.

Post Reply