skip to main content
OpenEdge Development: ADM and SmartObjects
SmartObjects : SmartDataObjects
A SmartDataObject is an ADM data‑class SmartObject that defines a set of records to fetch from a database. SmartDataObjects coordinate with other SmartObjects such as SmartDataViewers and SmartDataBrowsers to manage records in an application. Also, SmartDataObjects respond to navigation controls such as those available in SmartPanels and SmartToolbars.
The SmartDataObject is a nonvisual object; it has no run‑time visualization and needs a visualization or user‑interface (UI) object to display data. The visualization can exist in many forms, both Progress and non‑Progress, and is defined independently of the SmartDataObject itself.
Table 2–5 lists the SmartDataObject files.
Table 2–5: SmartDataObject files 
File type
Filename / SmartLinks
Template file
(standard SmartDataObject template with wizard)
Primary include file
ADM/Progress Advisor‑supported SmartLinks
Properties dialog box
src/adm2/support/datad.w (source code)
gui/adm2/support/datad.r (compiled code)
SmartDataObject instance properties
Figure 2–2 shows the SmartDataObject Properties dialog box.
Figure 2–2: SmartDataObject Properties dialog box
The properties in this dialog box are used as follows:
*Partition — This is the name of a partition: a logical grouping of one or more Progress procedures; for example, a set of procedures for managing inventory. The Partition Deployment Tool maps a partition to an Application Service, which defines where the SmartDataObject runs (which could be on an AppServer™).
*Rows To Batch — This is the number of rows to retrieve at a time from the data source and be stored by the client. The AppBuilder assigns the specified value to the RowsToBatch property. The default is 200.
*Check Current Changed — If this is checked, Progress checks on update whether records in the data source were changed since they were retrieved by this instance of the SmartDataObject. The AppBuilder sets the value for the CheckCurrentChanged property to YES if this toggle box is checked; otherwise, NO. The default is YES.
*Rebuild Dataset on Reposition — If this is checked, Progress rebuilds the temp-table on reposition starting with the specified record. If unchecked, the temp-table is rebuilt starting from the beginning of the data set. The AppBuilder sets the value for the RebuildOnRepos property to YES if this toggle box is checked; otherwise, NO. The default is NO.
*Force to Stateful Operating Mode If this is checked, the SmartDataObject runs in state‑aware mode regardless of the AppServer’s operating mode. If unchecked, the SmartDataObject inherits its operating mode from the AppServer. The default is NO.
*Destroy on each stateless Web Request — If checked, this destroys the SmartDataObject between requests. The default (unchecked) behavior is to keep the SmartDataObject alive between requests. Checking this property disables the Disconnect AppServer on each Web Request property.
Note: This property is disabled when the SmartDataObject Properties dialog box is used for non‑Web SmartDataObjects.
*Disconnect AppServer on each Web Request — If checked, this specifies that the AppServer part of the SmartDataObject is destroyed on each request but the client part remains alive. This allows you to use the Force to Stateful Operating Mode property without locking the AppServer for the lifetime of the SmartDataObject.
Note: This property is disabled when Destroy on each stateless Web Request is checked. It also is disabled when the SmartDataObject Properties dialog box is used for non‑Web SmartDataObjects.
SmartDataObject usage notes
This section provides specific usage notes on several SmartDataObject issues; however, because SmartDataObjects are the heart of any Progress ADM application, all remaining chapters of this manual (except Chapter 3, “SmartLinks”) also provide additional information on using them. In particular, see the following sections in Chapter 7, “Developing Your Application's Business Logic”:
*The “SmartDataObject query and update operations” section (RowObject and RowObjUpd temp-tables).
*The “Managing SmartDataObjects in distributed mode” section (Partition property).
*The “AppServer-related SmartDataObject properties” section (AppServer operating modes and the Force to Stateful Operating Mode property).
*The “Running SmartDataObjects in a distributed environment” section (the client/AppServer configuration for SmartDataObjects).
Setting the number of database rows to batch
The result set retrieved by a SmartDataObject’s database query is transferred into a Progress temp-table called RowObject that consists of the columns defined for the SmartDataObject. For a description of the RowObject temp-table, see the “SmartDataObject query and update operations” section.
If the query defines a large data set, it might take Progress a considerable amount of time to load all the database records into this temp-table for transmission to the client. For this reason, Progress transfers rows to the RowObject table a batch at a time, rather than one at a time. The default number of rows to batch, stored in the RowsToBatch property, is 200. In many cases, this is a reasonable number; however, you might want to adjust the value of this property up or down, depending on your expectations about the database query and how it will be used. You do this by specifying a value for the Rows To Batch field in the SmartDataObject’s instance properties dialog box.
Suppose, for example, you expect your SmartDataObject’s query to yield a data set that is slightly larger than 200 rows. In this case, you might want to set Rows To Batch high enough to retrieve the entire data set when the query first opens. This ensures there are no further delays if it is necessary to fetch more rows later. Conversely, if the startup time for your application screen is very sensitive, you might be able to improve startup performance noticeably by setting Rows To Batch to a very small number, to display the first batch of rows to the user as fast as possible.
Once you set this value at design time, you are not locked into that value for the entire time the application is run. You might choose to set Rows To Batch to an initial value at design time, then modify it programmatically at run time, based on the particular query being executed or on other factors.
As a general rule, you should limit the size of the data set the application code retrieves. Allowing users to browse thousands of records to make a selection is often an inefficient and ineffective way to present data, especially if the records must all be passed across an AppServer connection. Using a SmartFilter or SmartSelect SmartObject or other technique to refine the retrieval to the actual records needed can greatly increase the efficiency of an application and essentially eliminate issues with the size of the data set.
Checking database records on update attempts
By default, when an application user tries to update a SmartDataObject row, Progress checks whether the database record from which the row was derived was modified since the record was read into the RowObject temp-table. If so, Progress rejects the update attempt and returns to the client the values that result from the update that occurred since the record was read (by another user) along with an error message, so the user can make and save the later updates.
Note: This check does not include a field‑by‑field comparison of fields modified by a later user with fields modified by an earlier user. Unless the check is disabled, any change to any field in the record will cause the rejection of a later update.
In general, this check for other updates is valuable because it prevents making conflicting changes to a record; specifically, having a later set of changes overwrite an earlier set. In some cases, however, it might not matter whether a record was changed since it was read into the RowObject temp-table. You can set the CheckCurrentChanged property to instruct Progress not to check for earlier updates. Suppose, for example, your database table contains information such as address data, and it does not matter whether one user changes a field value in this table after another user changes a field value (either the same field or another one in the same table). In this case, the check is not necessary, and you can disable it by unchecking the Check Current Changed toggle box in the SmartDataObject’s instance property dialog box.
Changing how Progress reloads the RowObject temp-table
By default, Progress loads the RowObject temp-table from beginning to end. If a SmartDataObject’s query defines a large data set, a fetchLast operation or other reposition to a place far down the data set can result in a significant wait while Progress loads this temp-table. This is because Progress might need to load many batches of rows before it reaches the desired row.
To eliminate this delay, use the SmartDataObject’s RebuildOnRepos property, accessible through the Rebuild Dataset on Reposition toggle box in the instance properties dialog box. If you check this toggle box, then whenever a reposition moves to a record that is not already in the RowObject table, Progress performs the reposition in the database query directly and rebuilds the RowObject temp-table from that point.
For example, if the RowsToBatch property is set to 200 for a particular SmartDataObject, the first 200 rows in the database query data set are transferred into the RowObject temp-table when the SmartDataObject’s query is opened. Now, suppose an application user presses the Last button in an associated SmartPanel or SmartToolbar. Progress repositions the database query directly to the last row, and the RowObject table is rebuilt to contain the last 200 rows in the query. (Note that repositioning to the last row is a very fast operation if the INDEXED-REPOSITION query attribute is set to on and the query can use an index to locate the last record.) Progress extends the RowObject temp-table in both directions as the user scrolls forward or backward.
In general, if a SmartDataObject’s query returns a large data set, you should turn the RebuildOnRepos property to on. If the likely number of rows in the data set is not much larger than the setting for RowsToBatch, however, it is better to leave this property off and get the entire data set.
The Define Temp-Tables option
Typically, a SmartDataObject directly accesses the database tables for which it is defined. However, the SmartDataObject wizard provides an option called Define Temp-Tables that you can use at design time to define your own data source. With this option, you define Progress temp-tables for the database tables, which the SmartDataObject accesses instead of the database; each of these temp-tables can contain a subset of the fields in the corresponding database table as well as summary and calculated fields.
Note: The temp-tables that this option creates have no connection to the RowObject and RowObjUpd temp-tables that a SmartDataObject uses to manage database data. Those temp-tables are created and maintained automatically.
To define temp-tables for a SmartDataObject, in the AppBuilder:
1. Select the SmartDataObject icon from the AppBuilder palette and specify New. The SmartDataObject wizard appears.
2. Click Next to go to Page 2 of the SmartDataObject wizard.
3. Click Define Temp-Tables. The Temp-Table Maintenance dialog box appears.
4. Specify the database tables you want the SmartDataObject to access, using the Add and Remove buttons as necessary. The AppBuilder creates temp-tables for the tables you specify.
5. Click OK to return to the SmartDataObject wizard.
6. Click Define Query. The Query Builder appears.
7. In the Query Builder’s Database field, select Temp-Tables from the drop‑down list, then proceed as usual to build the SmartDataObject’s query.
Note: The compiler does not support the VALIDATE option on a temp-table field that is defined to be LIKE another temp-table field.
8. Click OK to return to the SmartDataObject wizard.
9. Click Next to go to Page 3.
10. Click Add fields. The Column Editor appears.
11. Specify the fields to be included in the SmartDataObject, then click OK to return to the SmartDataObject wizard.
12. Click Next to finish creating the SmartDataObject.
You must be connected to a database with the name of the temp-table you create, to use it. When the SmartDataObject executes the query, it accesses these temp-tables rather than accessing the database tables directly.
Note: Progress neither populates the tables this option creates nor manages any other of their interactions with the database, so you must write the code to perform these activities. If you do not, you will receive a warning message when you run the application, and any visual objects connected to the SmartDataObject will not display data in their fields.