ODBC and Remote Data Objects (RDO)

*  What are Remote Data Objects(RDOs)?
*  Remote Data Objects (RDOs) vs. Data Access Objects(DAOs)
*  Key concepts of remote data objects – Cursor Drivers, Resultset Types, and Lock types
*  What is ODBC and how does it function?
*  How to access Oracle database using ODBC?
*  How to use Remote Data control?
*  How to use Remote data object – Command Executor application
Remote Data Objects (RDOs)  are used to access a remote database through ODBC. Accessing an ODBC data source using RDO is faster than accessing the same using DAO.

Remote Data Control is an ActiveX control that is used to access an ODBC data source using RDOs.  This is same as a Data Control,  except that the data control uses DAOs and Remote data control uses RDOs.

First let us understand RDO object model and key features of RDOs and ODBC. Then we will understand how to use Remote Data Control and RDOs to access Oracle through ODBC.

Remote Data Object (RDO) Object Model
RDO object model is very small compared with DAO object model. Here is the list of objects in RDO object model. And most of them have their counterparts in DAO.
 
Here is a brief description about each object in the object model.

RDO object
Description
rdoEngine
The base object. Created automatically when you first access RDO in your application.
rdoError
Used to handle all ODBC errors and messages generated by RDO. Created automatically.
rdoEnvironment
Defines a logical set of connections and transaction scope for a particular user name. Contains both open and allocated (but unopened) connections, provides mechanisms for simultaneous transactions, and provides a security context for data manipulation language (DML) operations on the database. rdoEnvironments(0) created automatically.
rdoConnection
Represents an open connection to a remote data source and a specific database on that data source, or an allocated but as yet unconnected object, which can be used to subsequently establish a connection.
rdoTable
Represents the stored definition of a base table or an SQL view.
rdoResultset
Represents the rows that result from running a query.
rdoColumn
Represents a column of data with a common data type and a common set of properties.
rdoQuery
An SQL query definition that can include zero or more parameters.
rdoParameter
Represents a parameter associated with an rdoQuery object. Query parameters can be input, output, or both.
Table  18.1: Objects in RDO object model.

Note: rdoPreparedStatement is obsolete. It is supported only for backward compatibility. Microsoft recommends you use rdoQuery instead.

Remote Data Objects (RDOs) vs. Data Access Objects (DAOs)
Fundamentally RDO is same as DAO and  Remote data control is same as Data control.  However, RDO was designed and implemented strictly for relational databases that are accessed using ODBC. RDO doesn’t have a query engine like DAO, instead it depends on the query processor of the database that it is accessing.

The following table compares RDO objects and options with DAO objects and options.

Remote Data Objects and their DAO/Jet Equivalents

RDO object
Equivalent DAO/Jet object
rdoEngine
DBEngine
rdoError
Error
rdoEnvironment
Workspace
rdoConnection
Database
rdoTable
TableDef
Not Implemented
Index
rdoResultset
Recordset
Not implemented
Table-type
Keyset-type
Dynaset-type
Static-type (read/write)
Snapshot-type (readonly)
Dynamic-type
(none)
Forward-only – type
Forward-only-type
(cursorless)
(none)
RdoColumn
Field
RdoQuery
QueryDef
RdoParameter
Parameter
Not Implemented
Relation
Not Implemented
Group
Not implemented
User
Table 18.2 : Comparing RDO object with DAO object

Important concepts of RDO
There are three important concepts related to RDO. When you use RDO,  you have to first understand these three concepts. These concepts are:

¨         Cursor Drive
¨         Dataset (ResultSet) Type
¨         Lock Type

The following section will discuss about each of these three concepts. Understanding them is important because even ADOs use the same concept. In fact, most of the knowledge you gain with RDOs is usable with ADOs.

Cursor Drives
Cursor is the area where records are stored in memory. The process of keeping track of location of data pointer in the dataset is called as cursor management.  Which type of cursor you have to choose, it depends upon the functionality that you want. But remember that the choice you make regarding cursor will have impact on the performance.

The property used to indicate the type of cursor to be used is –  CURSORDRIVER.

The options available are:

Value
Driver Option
Meaning
0
RdUseIfNeeded
Specifies that the best cursor driver is to be used. This is the default.  RDO tries to use server side cursor first. If it is not available then it uses client side cursor.                                                                                           
1
RdUseODBC
Cursor is created on client by ODBC. Keysets of the records are stored in client’s RAM (extending to disk in case if it exceeds).
2
RdUseServer
Uses cursor of the remote database to manage records.
3
RdUseClientBatch
Primarily provided to support complex features, such as batch updates, multi-table updates, support for BLOB types etc.
Table 18.3: Available Cursor Driver options.

Basically you have to choose between keeping server on the client or keeping it on the server. If it is to be on the server, then database server should take care of it.

ResultSet Types
A Resultset is a collection of records.  The following are various types of ResultSets. Remember, not all resultsets are supported by cursor drivers.

The property used to indicate the type of result set is  - RESULTSETTYPE

Value
ResultSet Type
Description
0
RdOpenFowardOnly
Creates a forward only dataset.  All members of the dataset are copied to the client. This is the default.
1
RdOpenKeyset
This is an updateable dataset. New records added to the resultset will appear as part of the set. Record keys are created to point to all the members of the set.  Can contain columns from one or more tables.
2
RdOpenDynamic
The data reflects the changes made by other users.
3
RdOpenStatic
The dataset is updateable. But new records added, updated, and deleted  by other users may NOT appear as part of the set. To update ResultSet with up-to-date data you must reopen the ResultSet.
Table 18.4: Available ResultSet types.


Lock Type
This specifies the type of lock to be obtained while making changes to the ResultSet.  The following are the available options.

The property used to indicate locking type is – LOCKTYPE.

Value
Lock Type
Description
0
rdConcurReadOnly
Cursor is readonly and no updates are allowed. This is the default option. Use this if you do not have to modify the dataset.
1
rdConcurLock
Provides pessimistic locking. Each page touched by the current row in the resultset is locked. This is used only in special cases.
2
rdConcurRowver
Provides optimistic locking based on internal row id. Page is locked only when Update method is being executed. Records are not locked even between Edit and Update.
3
rdconcurvalues
Same as rdCoucurRowver, but it is based on the values of the columns and not the row id.
4
rdconcurBatch
Optimistic lock used for batch updates.
Table 18.5: Available locking types

Note: If you want to modify data in a Resultset, change the default setting of LockType. Because by default LockType is set to readonly, you can not make any changes to ResultSet.

Note: Whether a single row is locked or an entire page is locked and whether lock will be escalated etc, are database dependent.  For example, databases like Oracle can lock a single row, whereas Jet engine deals with page locking (a page is 2 KB).

Before we use RDOs to access an ODBC Data source, we have to understand ODBC. The following sections will discuss what is ODBC and how to access Oracle using ODBC.

What is ODBC?
ODBC (Open Database Connectivity) is an interface through which you can access data in heterogeneous environments. For example, using ODBC you can access data of DB2 running on Mainframe and you can access data of Oracle running on Sun Sparc and so on. ODBC is an interface that was promoted by Microsoft. First let us understand why we need ODBC and its importance in the industry.

Why do we need ODBC?
Assume you want to access data stored in Oracle from a program written in Visual Basic. For this, you use a set of functions supplied by Oracle called as APIs (also called as Oracle Call Interface (OCI)) to access Oracle database. In the same way each database vendor supplies a set of functions using which you can access the database. But the problem is, each set of functions is different from others. That means if you want to access Oracle using OCI, you have to learn how to use these functions. But tomorrow if you have to access Sybase, you have to use functions provided by Sybase to access its database. That not only makes the life of programmer tough (as he has to learn a new set of functions again), it also necessitates great amount of changes to your programs. In brief, each DBMS provides its own set of functions to access its database. So your program becomes database dependent. That means a change in the type of database (say from Sybase to Oracle) needs the program to be modified to a larger extent.

When things were getting more heterogeneous and database independent programs were much desired, Microsoft designed a new interface called Open Database Connectivity (ODBC). What is so great about ODBC.  Well, in nutshell, it makes your program database independent. That means whether you access Oracle or Sybase or DB2, you write the program and in the same manner you can shift your database from one to another.

How does ODBC Function?
To understand how does ODBC function, Each database vendor provides a program called as ODBC driver, which takes standard ODBC calls and translates them into the language the database can understand. So the application uses ODBC calls (called as ODBC API) either directly or indirectly (for example RDOs calling required ODBC calls) to access the database. And these ODBC calls are translated by ODBC driver of the specific database to the required native language.  As a result the program uses the same ODBC calls irrespective of the database it is accessing and the ODBC driver takes care of converting the standard calls to the native calls.

But how does system know which ODBC driver to use?. Where are these drivers? Where is the information regarding these drivers? Who supplies ODBC drivers? We have to answer to these questions now.

First of all, each database vendor, such as Oracle corporation, Microsoft , IBM and so on,  provides ODBC driver for its database. Remember if you do not have ODBC driver you cannot access the database using ODBC interface. It should also be noted, that there are some third party ODBC drivers. There are companies that are specialized in creating ODBC drivers, for example Intersolv.

You have to load ODBC drivers for database that you need to access. For example, if you want to access Oracle, you need to load ODBC driver for Oracle. When you load ODBC driver, Windows OS stores the details of the driver in System Registry (a part of Windows where important information is stored).

ODBC driver manager which is a part of Windows OS loads the required ODBC driver and passes the calls to driver and takes results from driver and pass the result to Application.

ODBC driver manager comes to know about the driver to be used and the database to be accessed through using  Data source name (DSN) used by the application program.

Data Source Name
An ODBC data source is accessed using DSN.  Data source name is a name that identifies the following:

¨         The name of the database to be used
¨         The type of the database and the ODBC driver to be used to access the database

DSN is created using ODBC Data Source Administrator, which is a program supplied by Windows OS. It is available in Control panel. When an application intends to access ODBC data source, it will create ODBC data source name (DSN) and accesses database through DSN.

So let us summarize the entire process.

¨         Application sends ODBC calls to ODBC Driver Manager
¨         ODBC Driver Manger sends ODBC calls to the appropriate ODBC Driver
¨         ODBC Driver converts ODBC calls to the native calls and accesses the database. 

Accessing Oracle Database using ODBC
We have just understood various pieces involved in accessing an ODBC data source. Now let us access Oracle database through ODBC. For this purpose we could use either DAOs  or RDOs, but when it comes to accessing ODBC data source, RDO is the obvious choice.

Here are the steps in accessing Oracle:

¨         Makes sure Oracle is installed in your system and it is up and running. You can check that using SQL*Plus. If you are successfully connected to Oracle using SQL*Plus that means Oracle is accessible to you.
¨         Makes sure your system contains ODBC driver for Oracle. This can be done with ODBC Data Source Administrator.
¨         Create a DSN for Oracle database. Use ODBC Data Source Administrator.
¨         Use DSN in Visual Basic application to access Oracle database.
To create DSN to access Oracle:

1.      Start ODBC data source administrator by running ODBC (32 Bit) program from Control Panel of Windows OS.
2.      Select Driver tab and check whether you have ODBC driver for Oracle. It may have the name “Microsoft ODBC for Oracle”.  If no ODBC driver for Oracle is existing, you have to load one before proceeding.           
3.      Select User DSN tab and click on Add button.
4.      When Create New Data Source dialog is displayed, select Microsoft ODBC for Oracle (or some other driver meant for Oracle) and click on Finish button
5.      In Microsoft ODBC for Oracle setup dialog enter Oracle as Data Source Name, Oracle 7.3 database as Description.
6.      If you are using Personal Oracle, leave remaining blank. If you are using Oracle Server (Client/Server Oracle) then enter Oracle service name (the one that you enter as Host String in Sql*plus) as Server.
7.      Click on Ok.
8.      You should see a new entry in the list of User Data Sources.

That’s all you have to do to create a DSN to access oracle.

Using Remote Data Control to access Oracle
Let us first understand how to access Oracle using remote data control.

Follow the steps given below to use Remote data control to access EMP table of user Scott in Oracle database.

1.      Create a new project of Standard Exe type
2.      Select Project -> Components and select Microsoft RemoteData Control 6.0 to load it into project.
3.      Place remote data control on the form.
4.      Change the following properties of Remote data control

Property
Value
DataSourceName
Oracle (or whatever name you have given as DSN)
UserName
Scott
Password
Tiger
Prompt
rdDriverNoPrompt
Caption
EMP Table From Oracle
SQL
Select Empno, Ename from Emp

SQL property of Remote data control identifies the SQL command that is to be executed.

5.      Place two labels and two text boxes
6.      Change the following properties of these controls.

Control
Property
Value
Label1
Caption
Employee Number
Label2
Caption
Employee Name
Text1
DataSource
MSRDC1

DataField
Empno
Text2
DataSource
MSRDC1

DataField
Ename
Form
Caption
Details of Employees

7.      Run the project using F5.
Using Remote Data Objects to Access ODBC Data source
We have seen how to use Remote Data Control to access data in Oracle database through ODBC interface. Now let us access the same database using Remote Data Objects.

To access ODBC data source using RDOs, follow the steps given below:

¨         Establish a connection using Connection object
¨         Create a ResultSet using Connection object
¨         Manipulate the ResultSet created in step 2.
Now let us develop the sample application, which allows you to access any ODBC data source and access the data from any table based on the given  condition. This is a quite general program that can be used with any ODBC data source.

Here is what the application is supposed to do.

¨         When you start the application it prompts the user to enter DSN, username and password.
¨         If a valid connection is established then it will display the main form from where user can enter any query and get the result displayed on the form.
¨         It is also possible to execute commands other than Select. In this case the status of the executed command will be displayed.

Now, let us create the application.

1.      Create a new project of Standard Exe type
2.      Use Project->References to load Microsoft Remote Data objects
3.      Use Project-> Add Form and select ODBC Log In as the type of the form to be added to the project.
4.      Visual Basic adds a new form with the name frmODBCLogon. This form is used to take ODBC DSN, username and password.  ODBC Logon form has a lot of code written by Visual Basic to get the list of Data source names etc. We will modify a part of the code later.
5.      Change PasswordChar of txtPWD textbox to “*” so that * is displayed instead of the actual characters entered.
6.      Change Caption of the form (frmODBCLogon) to “Command Executor – ODBC Logon

1.      Select Project-> Properties and select  frmODBCLogon as the startup object
2.      Change the name of  Form1 to frmMain.
3.      Declare a public object of type rdoConnection in  General/declaration of  frmMain as follows


Public  con  as rdoConnection

Remove the code written for  cmdOK_Click event procedure of  frmODBCLogon and write the following code.

Private Sub cmdOK_Click()
Dim res As Integer
 Dim cs  As String
    On Error GoTo errlbl
    ' form connect string
    If cboDSNList.ListIndex > 0 Then
        cs = "DSN=" & cboDSNList.Text & ";"
        cs = cs & "Uid=" & txtUID.Text & ";"
        cs = cs & "pwd=" & txtPWD.Text
        ' connect to database
        Set frmmain.con = rdoEngine.rdoEnvironments(0).OpenConnection("", rdDriverNoPrompt, True, cs)
        frmmain.Show
    End If
    Unload Me
    Exit Sub
errlbl:
    res = MsgBox("Unable to connect. Do you want to try again", vbYesNo + vbQuestion, "Error")
    If res = vbYes Then
         Exit Sub
    Else
         Unload Me
    End If
End Sub
Listing 18.1 : Code for OK button in ODBC Logon form.

Note:  You many not need all the functionality of ODBC Logon form. But it doesn’t harm having it. So you need not modify either the code or control in ODBC Logon form. However, if you ever need to change it, you are free to do so. Because it is after all a form in which Visual Basic has placed required controls and required code.

As you see in cmdOk_Click event, when user clicks on OK button, we take the required information – DSN, username, and password  - from controls and create connect string. Then we have used connect string to connect to the database.  If connect fails we prompt user to specify whether he wants to try again.

If connection is successful then we display main form (frmMain) and unload ODBC logon form.

Working with the main Form
Now let us concentrate on the main form. Remember by the time you enter into main from, Con object of main form is having a valid connection to the required database.

Place controls on the form 

Change the properties of the controls as follows.

Control
Property
Value
Label1
Caption
Command
Text1
Name
txtCommand

Text
“”

Multiline
True
Text2
Name
txtresult

Text
“”

Multiline
True

Scrollbars
3-both
Command1
Name
CmdExecute

Caption
&Execute
Command2
Name
CmdQuit

Caption
&Quit

Write the following code for click event of cmdExecute.

Private Sub cmdExecute_Click()
Dim fword As String

' Take the first word and compare it with SELECT. If it is SELECT then execute select command and get
‘ the rows and display them txtResult text box

fword = Mid(txtcommand, 1, InStr(txtcommand, " ") - 1)
If UCase(Trim(fword)) = "SELECT" Then
   ' get selected rows and display them in textbox
   ExecuteSelect 
Else
   ‘ Execute the given command and display the number of rows effected by the command
   ExecuteNonSelect
End If

End Sub
Lisgting  18.2: Code for click event of Execute command button.

UCase function is used to convert the word to upper case and Trim function is used to remove any leading spaces.

ExecuteSelect and ExecuteNonSelect are two userdefined procedures. Here is the code for both the procedures.

Public Sub ExecuteSelect()

Dim rs As rdoResultset
Dim col As rdoColumn
Dim result As String

   On Error GoTo errlbl
   ' create a resultset
   Set rs = con.OpenResultset(txtcommand.Text)
  
   result = ""
   Do Until rs.EOF
      For Each col In rs.rdoColumns
        If (IsNull(col.Value)) Then
            result = result & " NULL "
        Else
            result = result & col.Value & "  "
        End If
      Next
      result = result & vbCr & vbLf
      rs.MoveNext
   Loop
  
   txtresult.Text = result
  
   rs.Close
   Set rs = Nothing
   Exit Sub

Errlbl:
  ‘ Invoke procedure to display error message
   DisplayError
  
End Sub

Public Sub ExecuteNonSelect()
Dim status As String

 On Error GoTo errlbl
 ' Execute nonselect command
 con.Execute txtcommand.Text
 ' displays the status
 status = "Rows Effected = " & con.RowsAffected & vbCr & vbLf
 txtresult.Text = status
 Exit Sub

errlbl:
 ‘ Display error messages
 DisplayError

End Sub
Listing 18.3: User-defined procedures - ExecuteSelect and ExecuteNonSelect.

In both the procedures we have error handling, which invokes DisplayError procedure to display error messages. 

DisplayError procedure uses rdoErrors collection to get the list of messages and displays the error messages in txtResult text box. Here is the code for DisplayError procedure.

Public Sub DisplayError()

Dim status As String
Dim err As rdoError
Dim nl as string

 Nl = vbcr & vblf

 status = "Error occurred:" & nl
 status = status & "============================" & nl

  For Each err In rdoEngine.rdoErrors
      status = status & err.Description & nl
  Next
 
  txtresult.Text = status

End Sub
Listing 18.4: DisplayError user-defined procedure.
And the code for Quit button is as follows:

Private Sub cmdQuit_Click()
  con.Close
  Set con = Nothing
  Unload Me
End Sub
Listing 18.5: Code for Quit button.

Test Run
We have completed the application. Let us run the application to test whether it does what we want.

1.      Run the project using F5.
2.      You get ODBC Logon form. Select Oracle73 from DSN combo box.(or whatever DSN is applicable in your machine)
3.      Enter Scott as username and Tiger as password.
4.      Click on Ok.
5.      At this stage, the application is trying to connect to the given database with the given username and password. If it is not successful you get a message asking whether you want to retry

1.      If connection is successful, it invokes main form and closes ODBC Logon form. If you have given username and password correctly you should see main form
2.      Enter  “SELECT * FROM EMP“  in Command textbox and click on Execute button.
3.      The application should respond by displaying all the rows of EMP table
4.      Now enter an update command into command textbox

5.      If the given command is successfully executed then you get the number of rows effected by the command
6.      Now enter an invalid command , and click on Execute button.
7.      As the name of the column (DEPT) is not valid, “Invalid column name” error is displayed.
We have seen how to use RDOs to access ODBC data source in the Command Executor application. This application should give you an idea regarding Remote data objects such as Connection, Resultset, Columns, and Errors. However, remember using RDO resembles using DAO. So if you are good in DAO, you could pick up RDOs quite fast. This is equally true of ADOs, which we will discuss in the next chapter.
 

No comments:

ODBC and Remote Data Objects (RDO)

*  What are Remote Data Objects(RDOs)?
*  Remote Data Objects (RDOs) vs. Data Access Objects(DAOs)
*  Key concepts of remote data objects – Cursor Drivers, Resultset Types, and Lock types
*  What is ODBC and how does it function?
*  How to access Oracle database using ODBC?
*  How to use Remote Data control?
*  How to use Remote data object – Command Executor application
Remote Data Objects (RDOs)  are used to access a remote database through ODBC. Accessing an ODBC data source using RDO is faster than accessing the same using DAO.

Remote Data Control is an ActiveX control that is used to access an ODBC data source using RDOs.  This is same as a Data Control,  except that the data control uses DAOs and Remote data control uses RDOs.

First let us understand RDO object model and key features of RDOs and ODBC. Then we will understand how to use Remote Data Control and RDOs to access Oracle through ODBC.

Remote Data Object (RDO) Object Model
RDO object model is very small compared with DAO object model. Here is the list of objects in RDO object model. And most of them have their counterparts in DAO.
 
Here is a brief description about each object in the object model.

RDO object
Description
rdoEngine
The base object. Created automatically when you first access RDO in your application.
rdoError
Used to handle all ODBC errors and messages generated by RDO. Created automatically.
rdoEnvironment
Defines a logical set of connections and transaction scope for a particular user name. Contains both open and allocated (but unopened) connections, provides mechanisms for simultaneous transactions, and provides a security context for data manipulation language (DML) operations on the database. rdoEnvironments(0) created automatically.
rdoConnection
Represents an open connection to a remote data source and a specific database on that data source, or an allocated but as yet unconnected object, which can be used to subsequently establish a connection.
rdoTable
Represents the stored definition of a base table or an SQL view.
rdoResultset
Represents the rows that result from running a query.
rdoColumn
Represents a column of data with a common data type and a common set of properties.
rdoQuery
An SQL query definition that can include zero or more parameters.
rdoParameter
Represents a parameter associated with an rdoQuery object. Query parameters can be input, output, or both.
Table  18.1: Objects in RDO object model.

Note: rdoPreparedStatement is obsolete. It is supported only for backward compatibility. Microsoft recommends you use rdoQuery instead.

Remote Data Objects (RDOs) vs. Data Access Objects (DAOs)
Fundamentally RDO is same as DAO and  Remote data control is same as Data control.  However, RDO was designed and implemented strictly for relational databases that are accessed using ODBC. RDO doesn’t have a query engine like DAO, instead it depends on the query processor of the database that it is accessing.

The following table compares RDO objects and options with DAO objects and options.

Remote Data Objects and their DAO/Jet Equivalents

RDO object
Equivalent DAO/Jet object
rdoEngine
DBEngine
rdoError
Error
rdoEnvironment
Workspace
rdoConnection
Database
rdoTable
TableDef
Not Implemented
Index
rdoResultset
Recordset
Not implemented
Table-type
Keyset-type
Dynaset-type
Static-type (read/write)
Snapshot-type (readonly)
Dynamic-type
(none)
Forward-only – type
Forward-only-type
(cursorless)
(none)
RdoColumn
Field
RdoQuery
QueryDef
RdoParameter
Parameter
Not Implemented
Relation
Not Implemented
Group
Not implemented
User
Table 18.2 : Comparing RDO object with DAO object

Important concepts of RDO
There are three important concepts related to RDO. When you use RDO,  you have to first understand these three concepts. These concepts are:

¨         Cursor Drive
¨         Dataset (ResultSet) Type
¨         Lock Type

The following section will discuss about each of these three concepts. Understanding them is important because even ADOs use the same concept. In fact, most of the knowledge you gain with RDOs is usable with ADOs.

Cursor Drives
Cursor is the area where records are stored in memory. The process of keeping track of location of data pointer in the dataset is called as cursor management.  Which type of cursor you have to choose, it depends upon the functionality that you want. But remember that the choice you make regarding cursor will have impact on the performance.

The property used to indicate the type of cursor to be used is –  CURSORDRIVER.

The options available are:

Value
Driver Option
Meaning
0
RdUseIfNeeded
Specifies that the best cursor driver is to be used. This is the default.  RDO tries to use server side cursor first. If it is not available then it uses client side cursor.                                                                                           
1
RdUseODBC
Cursor is created on client by ODBC. Keysets of the records are stored in client’s RAM (extending to disk in case if it exceeds).
2
RdUseServer
Uses cursor of the remote database to manage records.
3
RdUseClientBatch
Primarily provided to support complex features, such as batch updates, multi-table updates, support for BLOB types etc.
Table 18.3: Available Cursor Driver options.

Basically you have to choose between keeping server on the client or keeping it on the server. If it is to be on the server, then database server should take care of it.

ResultSet Types
A Resultset is a collection of records.  The following are various types of ResultSets. Remember, not all resultsets are supported by cursor drivers.

The property used to indicate the type of result set is  - RESULTSETTYPE

Value
ResultSet Type
Description
0
RdOpenFowardOnly
Creates a forward only dataset.  All members of the dataset are copied to the client. This is the default.
1
RdOpenKeyset
This is an updateable dataset. New records added to the resultset will appear as part of the set. Record keys are created to point to all the members of the set.  Can contain columns from one or more tables.
2
RdOpenDynamic
The data reflects the changes made by other users.
3
RdOpenStatic
The dataset is updateable. But new records added, updated, and deleted  by other users may NOT appear as part of the set. To update ResultSet with up-to-date data you must reopen the ResultSet.
Table 18.4: Available ResultSet types.


Lock Type
This specifies the type of lock to be obtained while making changes to the ResultSet.  The following are the available options.

The property used to indicate locking type is – LOCKTYPE.

Value
Lock Type
Description
0
rdConcurReadOnly
Cursor is readonly and no updates are allowed. This is the default option. Use this if you do not have to modify the dataset.
1
rdConcurLock
Provides pessimistic locking. Each page touched by the current row in the resultset is locked. This is used only in special cases.
2
rdConcurRowver
Provides optimistic locking based on internal row id. Page is locked only when Update method is being executed. Records are not locked even between Edit and Update.
3
rdconcurvalues
Same as rdCoucurRowver, but it is based on the values of the columns and not the row id.
4
rdconcurBatch
Optimistic lock used for batch updates.
Table 18.5: Available locking types

Note: If you want to modify data in a Resultset, change the default setting of LockType. Because by default LockType is set to readonly, you can not make any changes to ResultSet.

Note: Whether a single row is locked or an entire page is locked and whether lock will be escalated etc, are database dependent.  For example, databases like Oracle can lock a single row, whereas Jet engine deals with page locking (a page is 2 KB).

Before we use RDOs to access an ODBC Data source, we have to understand ODBC. The following sections will discuss what is ODBC and how to access Oracle using ODBC.

What is ODBC?
ODBC (Open Database Connectivity) is an interface through which you can access data in heterogeneous environments. For example, using ODBC you can access data of DB2 running on Mainframe and you can access data of Oracle running on Sun Sparc and so on. ODBC is an interface that was promoted by Microsoft. First let us understand why we need ODBC and its importance in the industry.

Why do we need ODBC?
Assume you want to access data stored in Oracle from a program written in Visual Basic. For this, you use a set of functions supplied by Oracle called as APIs (also called as Oracle Call Interface (OCI)) to access Oracle database. In the same way each database vendor supplies a set of functions using which you can access the database. But the problem is, each set of functions is different from others. That means if you want to access Oracle using OCI, you have to learn how to use these functions. But tomorrow if you have to access Sybase, you have to use functions provided by Sybase to access its database. That not only makes the life of programmer tough (as he has to learn a new set of functions again), it also necessitates great amount of changes to your programs. In brief, each DBMS provides its own set of functions to access its database. So your program becomes database dependent. That means a change in the type of database (say from Sybase to Oracle) needs the program to be modified to a larger extent.

When things were getting more heterogeneous and database independent programs were much desired, Microsoft designed a new interface called Open Database Connectivity (ODBC). What is so great about ODBC.  Well, in nutshell, it makes your program database independent. That means whether you access Oracle or Sybase or DB2, you write the program and in the same manner you can shift your database from one to another.

How does ODBC Function?
To understand how does ODBC function, Each database vendor provides a program called as ODBC driver, which takes standard ODBC calls and translates them into the language the database can understand. So the application uses ODBC calls (called as ODBC API) either directly or indirectly (for example RDOs calling required ODBC calls) to access the database. And these ODBC calls are translated by ODBC driver of the specific database to the required native language.  As a result the program uses the same ODBC calls irrespective of the database it is accessing and the ODBC driver takes care of converting the standard calls to the native calls.

But how does system know which ODBC driver to use?. Where are these drivers? Where is the information regarding these drivers? Who supplies ODBC drivers? We have to answer to these questions now.

First of all, each database vendor, such as Oracle corporation, Microsoft , IBM and so on,  provides ODBC driver for its database. Remember if you do not have ODBC driver you cannot access the database using ODBC interface. It should also be noted, that there are some third party ODBC drivers. There are companies that are specialized in creating ODBC drivers, for example Intersolv.

You have to load ODBC drivers for database that you need to access. For example, if you want to access Oracle, you need to load ODBC driver for Oracle. When you load ODBC driver, Windows OS stores the details of the driver in System Registry (a part of Windows where important information is stored).

ODBC driver manager which is a part of Windows OS loads the required ODBC driver and passes the calls to driver and takes results from driver and pass the result to Application.

ODBC driver manager comes to know about the driver to be used and the database to be accessed through using  Data source name (DSN) used by the application program.

Data Source Name
An ODBC data source is accessed using DSN.  Data source name is a name that identifies the following:

¨         The name of the database to be used
¨         The type of the database and the ODBC driver to be used to access the database

DSN is created using ODBC Data Source Administrator, which is a program supplied by Windows OS. It is available in Control panel. When an application intends to access ODBC data source, it will create ODBC data source name (DSN) and accesses database through DSN.

So let us summarize the entire process.

¨         Application sends ODBC calls to ODBC Driver Manager
¨         ODBC Driver Manger sends ODBC calls to the appropriate ODBC Driver
¨         ODBC Driver converts ODBC calls to the native calls and accesses the database. 

Accessing Oracle Database using ODBC
We have just understood various pieces involved in accessing an ODBC data source. Now let us access Oracle database through ODBC. For this purpose we could use either DAOs  or RDOs, but when it comes to accessing ODBC data source, RDO is the obvious choice.

Here are the steps in accessing Oracle:

¨         Makes sure Oracle is installed in your system and it is up and running. You can check that using SQL*Plus. If you are successfully connected to Oracle using SQL*Plus that means Oracle is accessible to you.
¨         Makes sure your system contains ODBC driver for Oracle. This can be done with ODBC Data Source Administrator.
¨         Create a DSN for Oracle database. Use ODBC Data Source Administrator.
¨         Use DSN in Visual Basic application to access Oracle database.
To create DSN to access Oracle:

1.      Start ODBC data source administrator by running ODBC (32 Bit) program from Control Panel of Windows OS.
2.      Select Driver tab and check whether you have ODBC driver for Oracle. It may have the name “Microsoft ODBC for Oracle”.  If no ODBC driver for Oracle is existing, you have to load one before proceeding.           
3.      Select User DSN tab and click on Add button.
4.      When Create New Data Source dialog is displayed, select Microsoft ODBC for Oracle (or some other driver meant for Oracle) and click on Finish button
5.      In Microsoft ODBC for Oracle setup dialog enter Oracle as Data Source Name, Oracle 7.3 database as Description.
6.      If you are using Personal Oracle, leave remaining blank. If you are using Oracle Server (Client/Server Oracle) then enter Oracle service name (the one that you enter as Host String in Sql*plus) as Server.
7.      Click on Ok.
8.      You should see a new entry in the list of User Data Sources.

That’s all you have to do to create a DSN to access oracle.

Using Remote Data Control to access Oracle
Let us first understand how to access Oracle using remote data control.

Follow the steps given below to use Remote data control to access EMP table of user Scott in Oracle database.

1.      Create a new project of Standard Exe type
2.      Select Project -> Components and select Microsoft RemoteData Control 6.0 to load it into project.
3.      Place remote data control on the form.
4.      Change the following properties of Remote data control

Property
Value
DataSourceName
Oracle (or whatever name you have given as DSN)
UserName
Scott
Password
Tiger
Prompt
rdDriverNoPrompt
Caption
EMP Table From Oracle
SQL
Select Empno, Ename from Emp

SQL property of Remote data control identifies the SQL command that is to be executed.

5.      Place two labels and two text boxes
6.      Change the following properties of these controls.

Control
Property
Value
Label1
Caption
Employee Number
Label2
Caption
Employee Name
Text1
DataSource
MSRDC1

DataField
Empno
Text2
DataSource
MSRDC1

DataField
Ename
Form
Caption
Details of Employees

7.      Run the project using F5.
Using Remote Data Objects to Access ODBC Data source
We have seen how to use Remote Data Control to access data in Oracle database through ODBC interface. Now let us access the same database using Remote Data Objects.

To access ODBC data source using RDOs, follow the steps given below:

¨         Establish a connection using Connection object
¨         Create a ResultSet using Connection object
¨         Manipulate the ResultSet created in step 2.
Now let us develop the sample application, which allows you to access any ODBC data source and access the data from any table based on the given  condition. This is a quite general program that can be used with any ODBC data source.

Here is what the application is supposed to do.

¨         When you start the application it prompts the user to enter DSN, username and password.
¨         If a valid connection is established then it will display the main form from where user can enter any query and get the result displayed on the form.
¨         It is also possible to execute commands other than Select. In this case the status of the executed command will be displayed.

Now, let us create the application.

1.      Create a new project of Standard Exe type
2.      Use Project->References to load Microsoft Remote Data objects
3.      Use Project-> Add Form and select ODBC Log In as the type of the form to be added to the project.
4.      Visual Basic adds a new form with the name frmODBCLogon. This form is used to take ODBC DSN, username and password.  ODBC Logon form has a lot of code written by Visual Basic to get the list of Data source names etc. We will modify a part of the code later.
5.      Change PasswordChar of txtPWD textbox to “*” so that * is displayed instead of the actual characters entered.
6.      Change Caption of the form (frmODBCLogon) to “Command Executor – ODBC Logon

1.      Select Project-> Properties and select  frmODBCLogon as the startup object
2.      Change the name of  Form1 to frmMain.
3.      Declare a public object of type rdoConnection in  General/declaration of  frmMain as follows


Public  con  as rdoConnection

Remove the code written for  cmdOK_Click event procedure of  frmODBCLogon and write the following code.

Private Sub cmdOK_Click()
Dim res As Integer
 Dim cs  As String
    On Error GoTo errlbl
    ' form connect string
    If cboDSNList.ListIndex > 0 Then
        cs = "DSN=" & cboDSNList.Text & ";"
        cs = cs & "Uid=" & txtUID.Text & ";"
        cs = cs & "pwd=" & txtPWD.Text
        ' connect to database
        Set frmmain.con = rdoEngine.rdoEnvironments(0).OpenConnection("", rdDriverNoPrompt, True, cs)
        frmmain.Show
    End If
    Unload Me
    Exit Sub
errlbl:
    res = MsgBox("Unable to connect. Do you want to try again", vbYesNo + vbQuestion, "Error")
    If res = vbYes Then
         Exit Sub
    Else
         Unload Me
    End If
End Sub
Listing 18.1 : Code for OK button in ODBC Logon form.

Note:  You many not need all the functionality of ODBC Logon form. But it doesn’t harm having it. So you need not modify either the code or control in ODBC Logon form. However, if you ever need to change it, you are free to do so. Because it is after all a form in which Visual Basic has placed required controls and required code.

As you see in cmdOk_Click event, when user clicks on OK button, we take the required information – DSN, username, and password  - from controls and create connect string. Then we have used connect string to connect to the database.  If connect fails we prompt user to specify whether he wants to try again.

If connection is successful then we display main form (frmMain) and unload ODBC logon form.

Working with the main Form
Now let us concentrate on the main form. Remember by the time you enter into main from, Con object of main form is having a valid connection to the required database.

Place controls on the form 

Change the properties of the controls as follows.

Control
Property
Value
Label1
Caption
Command
Text1
Name
txtCommand

Text
“”

Multiline
True
Text2
Name
txtresult

Text
“”

Multiline
True

Scrollbars
3-both
Command1
Name
CmdExecute

Caption
&Execute
Command2
Name
CmdQuit

Caption
&Quit

Write the following code for click event of cmdExecute.

Private Sub cmdExecute_Click()
Dim fword As String

' Take the first word and compare it with SELECT. If it is SELECT then execute select command and get
‘ the rows and display them txtResult text box

fword = Mid(txtcommand, 1, InStr(txtcommand, " ") - 1)
If UCase(Trim(fword)) = "SELECT" Then
   ' get selected rows and display them in textbox
   ExecuteSelect 
Else
   ‘ Execute the given command and display the number of rows effected by the command
   ExecuteNonSelect
End If

End Sub
Lisgting  18.2: Code for click event of Execute command button.

UCase function is used to convert the word to upper case and Trim function is used to remove any leading spaces.

ExecuteSelect and ExecuteNonSelect are two userdefined procedures. Here is the code for both the procedures.

Public Sub ExecuteSelect()

Dim rs As rdoResultset
Dim col As rdoColumn
Dim result As String

   On Error GoTo errlbl
   ' create a resultset
   Set rs = con.OpenResultset(txtcommand.Text)
  
   result = ""
   Do Until rs.EOF
      For Each col In rs.rdoColumns
        If (IsNull(col.Value)) Then
            result = result & " NULL "
        Else
            result = result & col.Value & "  "
        End If
      Next
      result = result & vbCr & vbLf
      rs.MoveNext
   Loop
  
   txtresult.Text = result
  
   rs.Close
   Set rs = Nothing
   Exit Sub

Errlbl:
  ‘ Invoke procedure to display error message
   DisplayError
  
End Sub

Public Sub ExecuteNonSelect()
Dim status As String

 On Error GoTo errlbl
 ' Execute nonselect command
 con.Execute txtcommand.Text
 ' displays the status
 status = "Rows Effected = " & con.RowsAffected & vbCr & vbLf
 txtresult.Text = status
 Exit Sub

errlbl:
 ‘ Display error messages
 DisplayError

End Sub
Listing 18.3: User-defined procedures - ExecuteSelect and ExecuteNonSelect.

In both the procedures we have error handling, which invokes DisplayError procedure to display error messages. 

DisplayError procedure uses rdoErrors collection to get the list of messages and displays the error messages in txtResult text box. Here is the code for DisplayError procedure.

Public Sub DisplayError()

Dim status As String
Dim err As rdoError
Dim nl as string

 Nl = vbcr & vblf

 status = "Error occurred:" & nl
 status = status & "============================" & nl

  For Each err In rdoEngine.rdoErrors
      status = status & err.Description & nl
  Next
 
  txtresult.Text = status

End Sub
Listing 18.4: DisplayError user-defined procedure.
And the code for Quit button is as follows:

Private Sub cmdQuit_Click()
  con.Close
  Set con = Nothing
  Unload Me
End Sub
Listing 18.5: Code for Quit button.

Test Run
We have completed the application. Let us run the application to test whether it does what we want.

1.      Run the project using F5.
2.      You get ODBC Logon form. Select Oracle73 from DSN combo box.(or whatever DSN is applicable in your machine)
3.      Enter Scott as username and Tiger as password.
4.      Click on Ok.
5.      At this stage, the application is trying to connect to the given database with the given username and password. If it is not successful you get a message asking whether you want to retry

1.      If connection is successful, it invokes main form and closes ODBC Logon form. If you have given username and password correctly you should see main form
2.      Enter  “SELECT * FROM EMP“  in Command textbox and click on Execute button.
3.      The application should respond by displaying all the rows of EMP table
4.      Now enter an update command into command textbox

5.      If the given command is successfully executed then you get the number of rows effected by the command
6.      Now enter an invalid command , and click on Execute button.
7.      As the name of the column (DEPT) is not valid, “Invalid column name” error is displayed.
We have seen how to use RDOs to access ODBC data source in the Command Executor application. This application should give you an idea regarding Remote data objects such as Connection, Resultset, Columns, and Errors. However, remember using RDO resembles using DAO. So if you are good in DAO, you could pick up RDOs quite fast. This is equally true of ADOs, which we will discuss in the next chapter.
 

No comments: