CSDemos Sample Conversion


Let's do a practice run just to see how to convert an application to IBO from the BDE. I recommend that this article be printed out and followed very closely. Skipping one little step may cause some confusion and it's easy to do this when jumping between programs. Also, I am going to assume that you are using Delphi 4 or higher. This is because the TDataset class significantly changed from D3 to D4.

Quick Conversion
Get the tool GReplace I mentioned in the Converting To IBO Classes topic and run it. Please follow these steps in order to do the conversion:

·Open up the CSDemos.REP file in the TDatasetSamples folder of IBO.  
·Examine the Replace Text tab if you wish. It is setup with the necessary strings to completely convert this application.  
·Change to the Source tab and make sure that it is pointing to the right directory where Delphi is installed.  
·Change to the Destination tab and at the bottom of this tab is a button saying "GO". Click it.  
·Now open up in Delphi the project you just created in the TDatasetSamples\IBOCSDemos folder.  
·Simply run it. You are done. No further changes are required.  

If you don't have this tool then you get to go through all the units in this project and do the search and replace manually. Please get the items you need to search and replace by opening that *.REP file in a text editor of your choice.

The following topics offer some additional suggestions to consider with this sample application.

KeyLinks
Manually setting the keyLinks property relieves much of the system metadata queries trying to figure this out automatically. This isn't required to do but I recommend that it be done.

Investigate the primary keys of each table used by double clicking on the TIBODatabase component Employee database to get at its component editor. On the Connection tab there is a button that says "Browse". Click it and go to the Relations tab where all of the tables are listed. Select the CUSTOMER table from the list and notice the PK in the third column of the grid on the line with the CUST_NO field. This is the primary key for the table. The following primary keys were discovered from the rest of the tables:

CUSTOMER: CUSTOMER.CUST_NO  
DEPARTMENT: DEPARTMENT.DEPT_NO  
EMPLOYEE: EMPLOYEE.EMP_NO  
PROJECT: PROJECT.PROJ_ID  
SALES: SALES.PO_NUMBER  

Place these columns in the KeyLinks property of each relevant TIBOTable component. Be sure to visit the frmViewDemo and set its VaryingTable.KeyLinks to EMPLOYEE.EMP_NO too. It is a good habit to get into to use the table name with the columns in the KeyLinks property.

With the SALES_HISTORY_TABLE simply set KeyLinksAutoDefine to false so that it will not query the system metadata. There aren't any operations being performed on this table that requires the use of the KeyLinks settings.

On the frmQueryProc form set the EmployeeProjectsQuery KeyLinksAutoDefine property to false as well.

DeleteSQL
Rather than use a separate query and lines of application code to make a stored procedure responsible for carrying out the delete of a record it is possible to take advantage of the DeleteSQL property to tell IBO that a stored procedure should be used to perform the actual delete.

Go to the EmployeeTable on the main data module and set the DeleteSQL property as follows:

EXECUTE PROCEDURE DELETE_EMPLOYEE ( :OLD_EMP_NO )  

I
n this way IBO will execute this when posting the delete. Any exception that the stored procedure raises will be caught and the delete will fail and the appropriate error message will be displayed.

Once this change has been made simply delete the DeleteEmployeeProc and the lines of code in the BeforeDelete event that used it. Feel free to test it out and toast a few employees, kinda like Inprise did recently... (mid-1999)

InvalidateBookmark
Go to the Frmexesp and double-click on the Ship Order button to go to the source code assigned to it. Replace the call to SalesTable.Refresh with the following line of code:

SalesTable.InvalidateBookmark( SalesTable.Bookmark );  

You can also use:

SalesTable.InvalidateRowNum( SalesTable.RecNo );  

What this will do is instead of refreshing the entire dataset, which is totally unnecessary, it will refresh just the row that was affected by the operation performed in the stored procedure just above it. Thus only one row is fetched from the server.

An Oddity to Beware of
I noticed a discrepancy in how this application was configured to handle scaled numeric columns. In the SalesTable there is a column called TOTAL_VALUE that is given a design-time field of type TIntegerField. However, in the database it is declared as NUMERIC( 9, 2 ) which means that it should allow for two places after the decimal point. But, by using a TIntegerField it makes it so that the two decimal places are stripped off and unaccessable. I think this is a bug in the BDE/VCL but since I am emulating the BDE I have made IBO able to respond to this setting and use it if the TIBOFloatField (used by default in IBO) causes an exception during the fields binding process. You may notice an exception in the debugger but it is handled and will be transparent to the end-user when running the compiled app.

It is possible to delete the field from the fields editor and add it back in again to give it the proper IBO declared type of TFloatField. Then, the values beyond the decimal point will be properly displayed. The data for this column is viewable in the far right of the top grid on the Executable Stored Procedure Demo form. Don't be tricked though because the first few entries don't have any cents.

Even though the field may be bound to a TIBOFloatField it is still resolved to integer based storage on the server and in the local client buffers. Thus, any minor rounding anomalies are stripped off automatically.

The Quick Conversion automatically corrects this. Look closely in the Replace Text tab and you will see an entry that converts this integer field to the IBO float field. It could have been changed to a TIBOBCDField too.

SQL Trace Monitor
Just so that we can see what is going on behind the scenes, drop a TIB_MonitorDialog component (from the iboDialogs tab on the component palette) on the main form and set the following properties:

BaseKey: Software\Apps\IBO\CSDemos  
Caption: CSDemos  

BaseKey will take the preferences selected on this form and store them in the system registry.

Assign a FormCreate event for the form and place the following code in it:

IB_MonitorDialog1.Show;  

Then, while the application is running we will be keeping track of what is going on behind the scenes. Unfortunately, this application was designed using modal forms so we are somewhat inconvienced when we want to look at the trace log.

IBO's monitor is an in-process monitor and not an out-of-process monitor like the BDE has. This has its advantages and disadvantages...

Conclusion
Well, that wasn't so hard was it? This application now works just like it did before except that it no longer has the BDE associated with it and a few optimizations and a bug fix that were previously unavailable.

NOTE: This topic was revised at IBO version 3.6.