DataWindow recovery from an unexpected transaction disconnect PB

Symptom

Customer is using an OCX that causes the application to crash, due to a database driver issue. Until the database vendor corrects the driver issue, we have given them a workaround requiring them to disconnect from and reconnect to the database. Unfortunately, this terminates the transaction object connection and they need a way to reconnect their DataWindows.

Environment

OS: Windows 7 64-bit PowerBuilder Database: Informix 11.5

Reproducing the Issue

The following steps will demonstrate how to reproduce the issue:

  1. Download DWrecovery.zip.

  2. Unzip DWrecovery.zip into a local directory

  3. Open mdi.pbw workspace in PB IDE

  4. Run the application

  5. Select File > New > Untitled for Sheet1

  6. Display shows two populated DataWindows


  7. Left-click on "Employees" command button

  8. The top DataWindow will clear and eventually repopulate

  9. Left-click on "Reconnect" command button

  10. Left-click on "Employees" command button

  11. A DataWindow error will appear since DiSCONNECTing and CONNECTing to the database will cause Transaction Objects to disconnect as well.


Cause

Once the database disconnect occurs, all DataWindow Transaction objects will point to an invalid connection.

Solution

You can reset all DataWindows by reconnecting to the database and cycling through all open sheets to locate and reset all Transaction Objects: In the sample application, if you click on the "SQLCA Reset"command button after the earlier failure, the Transaction Objects will be restored on all DataWindows.

The initial call would be to a global function that looks for open sheets and by calling a function that resets the Transaction Object on all DataWindows restoring a valid database connection.

integerli_opensheet, li_opensheets
li_opensheets = UpperBound(inv_sheetmgt.iw_opensheets)
for li_opensheet = 1 to li_opensheets
   of_settransaction(inv_sheetmgt.iw_opensheets[li_opensheet], SQLCA)
next

The of_setransaction function would be coded as follows:

It has 2 parameters:

as_window of type window
as_transaction of type transaction object

PowerScript:

integerli_control, li_controls
WindowObjectlwo_control[]
lwo_control[] = as_window.Control[]
li_controls = UpperBound(lwo_control)
For li_control = 1 TO li_controls
   IF lwo_control[li_control].TypeOf() = DataWindow! THEN
   lwo_control[li_control].DYNAMIC SetTransObject(as_transaction)
END IF
NEXT