Subject RE: [IBO] Transaction.Refresh(True)
Author Alan McDonald
> Hi Alan,
> > I've just upgraded an oldish application to the latest IBO
> > 4.6.B from maybe 4.5 something.
> > I notice that the Transaction.Refresh(true) which I relied
> > on quite a bit, no longer refreshes the connected queries.
> > I now have to manually open and close them. This has to be
> > an issue with someone else no?
> I have now updated a test version of one of my apps to 4.6.Bc
> (still using FB v1.5.3 - as the app queries are not yet "fixed"
> to work with FB v2 yet).
> My immediate reaction is that everything seems to be working.
> By save button calls Transaction.Refresh(true) and the form
> I am looking at at the moment has lots of detail queries
> beneath a single master - all connected to the same
> transaction. I hit the save button and everything looks OK
> to me.
> Is there anything specific I should be looking for to see what
> you are seeing?
> Is there any chance that you are using CachedUpdates somewhere
> in your problem app? (I dont use CachedUpdates at all, but I
> notice that there were changes associated with CachedUpdates in
> the update.)
> --
> Geoff Worboys
> Telesis Computing

I don't use cached updates.
In this instance, make your queries open without first explicitly starting
their transaction, i.e. an implicit transaction start.
Start your app and open the server status form.
Watch your transaction (without doing anything else in the app) until it
does a timeout (AllowCheckOAT default to 120 secs - for testing you can
shorten this period)
The transaction will show as "Started - False" in the status form. The
queries will show active but the transaction has timed out.
This is all as expected so far.
Now start a second instance of your application and insert a record such
that it would normally be visible in your first instance and commit it.
Now hit your Save button in the first instance. There will be no exception
but the inserted record(s) which should now be visible, will not be visible
since the refresh action will not reopen the queries. (BTW these queries in
my case are on a readonly transaction)
This sequence used to restart (close and open) the queries. My application
relies on an event firing a transaction.refresh and users would see the
queries refresh with the new record but not now.

So the fix...
You need to test if the transaction is started/active: these 3 properties
will return different results depending upon an implicit start or an
explicit start.
IB_Transaction1.Started, or
This last one is the one I now rely on.
So I need to do this now:

bTransCanStart := False;
// Test is any queries are active - even when the transaction has timed
for i:=0 to IB_TransactionJobStatus.DatasetCount-1 do begin
if IB_TransactionJobStatus.Datasets[i].Active then
bTransCanStart := True;
// If at least one query is active, then I need to restart the
transaction if it has
// timed out. If no query is active, then this transaction is of no
interest to me
// so don't restart the transaction if it's not active (timed-out)
if not IB_TransactionJobStatus.InTransaction and bTransCanStart then
// So if there is at least one active query and the transaction has
// restart it
// Now you can use the Refresh method.
// Using it on a timeout transaction without the preceeding code, will
// restart the transaction BUT WILL NOT CLOSE AND OPEN the queries.

Once this method has been called, the transaction start is EXPLICIT, and the
behaviour is different but the above code will still work nicely. So it
works for both cases of implicit and explicit.

Bottom line...
The last line of the above code used to be all that was required. I still
like the solution, though, and I also appreciate the timeout feature from
the POV of saving system resources. and Oh, you can poke your finger at me
all you like for not making explicit transaction starts everywhere.

I found this out since operators can leave their application running on
these queries afte first loading the application. The transaction does a
timeout - nice, then one operator adds a record and noone sees it. All in
all, the above code is nice as a general save feature. I could also make it
cycle thru all the connection's transactions as a first step and would never
need to worry about which transaction should/shouldn't be started. Only the
transaction with active queries will be of interest.
I assume that in future releases, the queries will continue to report
active, even after their transaction has timed-out. Maybe they won't.