The local copy of data in the data set is manipulated by the user adding, updating, and deleting data. The editing is done in isolation from the original data in the data source.
"Resolving" is the process by which the changes to the local data are saved back to the original data source. If no other users have made updates to the same data, saving the updates is fairly simple. Resolver logic also helps you handle the cases where other users make independent changes to the data.
In JBuilder, the user-interface portion of any application typically includes one or more UI controls. The data access functionality is provided by additional data access components that have no user-interface of their own, but are connected through dataSet property of UI controls. Many types of UI controls can display data from a data set. However, JBuilder provides a number of "data-aware" controls which have a dataSet property. By simply setting the dataSet property, of a data-aware control to any of the JBuilder DataExpress data sets, the control becomes interactive with the data set.
The following figure illustrates a simple application where a user-interface control (in this case a GridControl) displays the results of a query executed against a server database. The figure shows the Data Access components needed for this application and how they connect to each other:
In other applications, you might use other dataset components, depending on the source of your data. The following table describes different sources of data and the corresponding Data Access component to use:
Use this component | When the data source is |
---|---|
QueryDataSet | the result set from a query execution |
ProcedureDataSet | the result set from a stored procedure execution |
TableDataSet | imported/loaded from a file or custom data source. Can also be created at run-time. |
For more information on the "providing" phase of your application, and issues that affect it, see the Accessing data chapter in this manual.
Once the data is stored in a JBCL DataSet component (regardless of whether you use a QueryDataSet, ProcedureDataSet, or TableDataSet), you manipulate the data in the same way because they all follow the DataSet API. For example, you connect a UI control to data in any DataSet by simply setting the UI control's dataSet property to that DataSet. Similarly, any non-visual and programmatic data manipulation is handled in the same way across all DataSet objects.
After your application has completed its manipulation and editing of to the local copy of the data, you typically save the changes back to the data source in a step referred to as "resolving". When saving the data to a text file, the resolving phase is at its simplest: the data is exported to a text file. When resolving back to a database server however, many things can happen to interrupt or prevent the resolving process. JBuilder's resolver logic provides events for handling resolution conflicts; you should write your application to handle these events appropriately.
Each of the above phases is described in more detail in later chapters of this manual. The advantage of such an architecture to the developer is its ease when customizing an application to a particular client's needs. Typically, the main logic of an application remains the same but the provider and resolver logic needs to be customized for each client. You can create custom provider and resolver portions for each while keeping the main logic of the application unchanged.
The core functionality required for data connectivity is contained in the borland.jbcl.dataset package of the JBCL. The components in this package encapsulate both the connection between the application and its source of the data, as well as the behavior needed to manipulate the data. While the package name is dataset, the features provided by this package include that of database connectivity as well as data set functionality.
The main classes and components in the dataset package are listed in the table below, along with a brief description of the component or class. The right-most column of this table lists frequently used properties of the class or component. Some properties are themselves objects that group multiple properties. These complex property objects end with the word Descriptor and contain key properties which (typically) must be set for the component to be usable.
Component/Class | Description | Frequently used properties |
Database | A required component when accessing data stored on a remote server, the Database component manages the JDBC connection to the SQL server database. | The ConnectionDescriptor object stores connection properties of user name, password, and connection URL. Accessed using the connection property. |
DataSet | An abstract class that provides basic data set behavior, DataSet also provides the infrastructure for data storage by maintaining a two-dimensional array that is organized by rows and columns. It has the concept of a current row position, which allows you to navigate through the rows of data and manages a "pseudo record" that holds the current new or edited record until it is posted into the DataSet. |
The SortDescriptor object contains properties that affect the order in which data is accessed and displayed in a UI control. Set using the sort property.
The MasterLinkDescriptor object contains properties for managing master-detail relationships between two DataSet components. Accessed using the masterLink property on the detail DataSet. |
StorageDataSet |
An abstract class that extends the DataSet class by providing implementation for storage of the data and manipulation of the structure of the DataSet.
You fill a StorageDataSet component with data by extracting information from a remote database (such as InterBase or Oracle), or by importing data stored in a text file. This is done by instantiating one of its subclasses: QueryDataSet, ProcedureDataSet (for stored procedures), or TableDataSet. |
The tableName property specifies the data source of the StorageDataSet component. The maxRows property defines the maximum number of rows that the DataSet can initially contain. The readOnly property controls write-access to the data. |
QueryDataSet | The QueryDataSet component stores the results of a query string executed against a server database. This component works with the Database component to connect to SQL server databases, and runs the specified query with parameters (if any). Once the resulting data is stored in the QueryDataSet component, you can manipulate the data using the DataSet API. | The QueryDescriptor object contains the query statement, query parameters, and database component. Accessed using the query property. |
ProcedureDataSet | The ProcedureDataSet component holds the results of a stored procedure executed against a server database. This component works with the Database component in a manner similar to the QueryDataSet component. | The ProcedureDescriptor object contains the query statement, query parameters, database component, and other properties. Accessed using the procedure property. |
TableDataSet | Use this component when importing data from a text file. This component extends the DataSet class by adding behavior that allows it to mimic SQL server functionality, without requiring a SQL server connection. | The (inherited) dataFile property specifies the file name from which to load data into the DataSet and to save the data to. |
DataSetView | This component presents an alternate "view" of the data in an existing StorageDataSet. It has its own (inherited) sort property, which, if given a new value, allows a different ordered presentation of the data. It also has filtering and navigation capabilities that are independent of its associated StorageDataSet. | The storageDataSet property indicates the component which contains the data that the DataSetView presents a view of. |
Column |
A Column represents the collection from all rows of a particular item of data, for example, all the Name values in a table. A Column gets its value when a DataSet is instantiated or as the result of a calculation.
The Column is managed by its StorageDataSet component. |
You can conveniently set properties at the Column level so that settings which affect the entire column of data can be set at one place, for example, font. JBuilder design tools include access to column-level properties by clicking to expand the plus sign (+) of any StorageDataSet implementation in the Component Tree, then selecting the Column that you want to work with. The selected Column component's properties and events display in the Component Inspector and can be edited there. |
DataRow |
The DataRow component is a collection of all Column data for a single row where each row is a complete record of information. The DataRow component uses the same columns of the DataSet it was constructed with.
A DataRow is convenient to work with when comparing the data in two rows or when locating data in a DataSet. It can be used in all DataSet methods that require a ReadRow or ReadWriteRow. |
|
DataModule | The DataModule is an interface in the dataset package. A class that implements DataModule will be recognized by the JBuilder designer as a class that contains various dataset components grouped into a data model. You create a new, empty data module by selecting the Data Module icon from the File | New dialog. Then using the Component Palette and Component Tree, you place into it various dataset objects, and provide connections, queries, sorts, and custom business rules logic. Data modules simplify reuse and multiple use of collections of dataset components. For example, one or more UI classes in your application can use a shared instance of your custom DataModule. |
There are several other classes and components in the dataset package as well as several support classes in other packages such as the util and view packages. In most cases, you don't need to know about these additional classes. Detailed information on the packages and classes of the JBCL is included in the JBCL Reference documentation.