Académique Documents
Professionnel Documents
Culture Documents
SYPRAM TECHNOLOGY
Copyright © 2001.
3. GETTING STARTED
i. USING THE LIBRARY IN VISUAL C++ PROJECT
ii. USING THE CLASSES
iii. CONNECTING TO DATA SOURCES
a. Connecting to data source using standard properties
i. Connecting to a JET database
ii. Connecting to an SQL Server database
iii. Connecting to an ORACLE database
iv. Connecting to an ODBC data source
b. Connecting to data source using custom properties
c. Setting the connection timeout property
d. Using OLE DB service components
ix. TRANSACTIONS
4. CONTACT INFORMATION
i. GETTING MORE INFORMATION
ii. TECHNICAL SUPPORT
*******************************************
When it comes to choosing the right data access technology for application
development, most Visual C++ programmers face a puzzling set of choices. Not only
are these choices limited, but also they are conflicting in terms of performance
requirement and ease of use. Whether it is a stand-alone application, a client/server
application or a web application, a C++ programmer would never like to compromise
the factors of decision such as performance, speed, and resource management. The
simple reason for this fact is the underlying tenet that the C++ programmers are
supposed to churn out the smartest applications in the programming world. Although
the type and make of the database as well as the nature of application can largely
influence the decision, it is not as easy as it seems.
Let us try to understand and analyze some of the most obvious data access choices:
Native Library:
Native libraries are supplied by many database vendors and they provide fastest data
access for the respective databases. However, due to the well-known fact that the code
written using a native library is not portable to other databases, your application gets
locked into the database vendor’s technology. Moreover, each native library is totally
different in nature compared to other libraries. So, we will not devote any time
discussing this option in detail and leave it to the developers to explore further on this
topic.
ADO:
Since its introduction, ADO has been the most widely used option for data access on
Windows platform. Though primarily designed and developed for Visual Basic and
scripting languages, it is not used less in Visual C++ world. After ODBC, ADO is the
major library that is proven and tested for data access on the Windows platform.
Thousands of developers, using various programming languages on the windows
platform, rely heavily on ADO for the data access needs of their applications. Having
said that, you might wonder why ADO is not an ideal choice for Visual C++
developers. Well, here is why:
BSTRs, C++ developers get a hitch. The reason for this disliking is
clearly understandable. Converting a VARIANT to and from the native
data types of C++ is really a pain. Not only does it call for extra work,
but also it affects the overall performance of the application.
c. Using ADO in Visual C++ also comes with other drawbacks and
limitations. If you use #import statement, you cannot avoid jump-to-
exception situation even if you want to avoid it. Additionally, you loose
flexibility of having default arguments to the methods. You must provide
all method arguments. If you use ADO SDK or raw COM interfaces,
you have to check for HRESULT values at each and every point. Since
data access code normally requires frequent method calls, it becomes
cumbersome to check these values.
Concluding on all the points mentioned above, we could say that ADO should be the
choice of data access for C++ programmers only if there is no other better choice.
Putting all these facts together, one can easily conclude that OLE DB consumer
classes have an edge over ADO. Yes, they definitely have. You might wonder then,
why in the world would any C++ programmer use ADO at all. Adding to your wonder
is the fact that more C++ developers use ADO in their applications than OLE DB
consumer templates. But, wait a minute. There are several good reasons for this fact.
Let us see. I am going to list a few of these reasons below.
a. Memory leaks & bugs : The OLE DB consumer templates contain several
Copyright©2001. Sypram Technology. www.sypram.com
5
EXPRESS OLE DB Library: User’sGuide
classes with bugs and memory leak problems. Most notable of them are the
methods of CDataSource class that leak memory and the column binding in
CDynamicAccessor class that does not handle wide characters properly. As
of Service Pack 5 of Visual Studio 6.0, these problems are not fixed.
b. Lack of features and flexibility: Although consumer templates are much easier
to use than raw OLE DB interfaces, they lack several features and
functionalities compared to ADO. Checking EOF/BOF status in a rowset,
handling BLOB data, refreshing and updating a rowset, and fetching error
details from HRESULT values are just a few of them to list. Using a data access
library without these features in your application is a lot of work in itself.
g. Steeper learning curve: Using OLE DB consumer templates for such basic
tasks as inserting and deleting rows from a database table is not a problem.
However, if you want to move little above that level, you need to understand
well the nitty-gritty of OLE DB. As for example, if you want to create an
updateable client-side cursor, not only a lot of work is needed, but also the firm
understanding of OLE DB interfaces is must. The fact remains that no matter
what technology you use, if you want to access databases at lower level, there is
no easy way. And consumer templates are no exception.
Considering all the aforementioned issues about ADO and consumer templates, the
fact becomes clearer that there is no panacea for C++ programmers as far as data
access is concerned. No single library is both sufficient as well as efficient. Although
consumer template classes are excellent tool for accessing databases, they are
incomplete in features and insufficient from an application development point of view.
EXPRESS OLE DB is a C++ class library that extends the OLE DB consumer
template classes and is a complete, feature-rich, and extremely powerful data access
solution for C++ programmers. It is built with the aim of eliminating the limitations
and drawbacks of consumer templates while still retaining power and performance of
consumer templates. Some of the features of this library can be summarized briefly as
follows:
2) Easy to learn: Many of the features of this library are modeled after ADO and, as
such, it is extremely intuitive. The bottom line is that if you know the basics of any
data access library, you can easily learn this one too.
3) Easy to debug: Several debug macros and validations are embedded in almost
every method in this library. This fact makes a big difference as far as application
debugging is concerned. Frequently, it is much easier to debug an application
written using EXPRESS OLE DB than the one written using ADO.
4) High performance: Although a large number of features have been added to the
library and a lot of care is taken to avoid errors as far as possible, a significant
effort has been made to keep it lightweight and reduce unnecessary overhead.
Basic benchmark tests show that a performance gain of EXPRESS OLE DB library
over ADO range from 20% to 200% depending upon various factors.
5) Rich in features: We have seen that consumer template classes lack several
functionalities and features that are necessary for such basic database operations as
checking for EOF, counting rows in a recordset, checking data type of a column
etc. So, almost all of these features are added in EXPRESS OLE DB.
6) XML support: EXPRESS OLE DB provides built-in support for XML. Using this
library, you can extract the column structure as well as any data from any source in
XML format.
8) Flexibility: The biggest advantage offered by this library is the flexibility it offers.
Take an example of error trapping. You have three different ways to control errors:
exceptions, error object, and custom class.
10) FREE: Above all other points, the biggest advantage is that the Express OLE
DB library is absolutely freely distributed by Sypram Technology.
CLASS HIERARCHY
As you can see in the figure above, Express OLE DB library contains several useful
classes. Based on their purpose and functionality, these classes can be divided into
three categories. The following paragraph illustrates these categories along with a
brief description of each class.
Operations classes
through any OLE DB provider. It also supports the transaction handling methods. The
class is designed after ADO’s Connection class.
Any data access library is not practically useful if it does not support data binding
with user interface controls. The most extensively needed control to display data is a
grid control. In relational databases, data need to be frequently presented in tabular
format and grid control is the best tool for that purpose.
Using Express OLE DB library, you can display data in Grid using two ways:
1. First, if you want to use MSGrid ActiveX control, you can convert a
CSypODLRecordset class (or CSypODLRecordBase class) into an
ADO Recordset class and then bind it to the MSGrid control. The advantage
here is that you do not need any third-party grid control library because MSGrid
control is bundled with Microsoft Visual Studio 6.0. However, many
programmers do not like using ActiveX controls in C++. Additionally, you are
depending on ADO to display data in grid and you have to bundle correct
Copyright©2001. Sypram Technology. www.sypram.com
10
EXPRESS OLE DB Library: User’sGuide
2. Second, you can directly bind the recordset object from Express OLE DB
library to commercial Grid libraries such as RogueWave® Stingray Studio. The
only drawback of this method is that you need to purchase third-party library in
order to get a license from the grid library vendor.
NOTE : The above two classes will work only if you have RogueWave® Stingray
studio library installed on your machine. For purchasing this product, contact
RogueWave at http://www.roguewave.com.
Utility classes
Utility classes are very useful in handling certain situations such as error trapping,
string manipulation, etc.
CSypODLChunk: This class facilitates memory management and reading and writing
operations for BLOB chunks.
Apart from all the aforementioned classes, Express OLE DB library also provides
some classes, which are built to correct (or enhance) some functionality of OLE DB
consumer templates. Each of this class is mentioned below:
LIMITATIONS
Although Express OLE DB library has been designed and developed to support a
wide range of applications, there are several areas, which are not addressed in this
version of library. Specifically, the following limitations exist in the current version of
the library
These features along with much other missing functionality are planned to be
supported in the future versions of the product. Particularly, our technical team is
working on a .NET based version of this library, which is going to include all of the
above functionalities.
SOFTWARE REQUIREMENTS
Express OLE DB library is compatible with the latest 32-bit release of Visual C++
6.0 and has been extensively tested with Visual Studio 6.0 Service Pack 5.
Express OLE DB library is designed primarily for use in MFC applications. However,
it can also be used with ATL provided that you add two MFC compliant classes:
CString and COleDateTime. These classes are freely available on several
Internet sites as well as in some third-party libraries.
If you are using the CD-ROM for installing, just insert the CD into the drive and the
setup program runs automatically. If you are using the downloaded version of
extractable setup, just double click the executable file. Once you start running the
program, most of the options are straightforward.
Once you successfully install the class library, it creates the following directories on
the target machine.
Before you proceed to use the EXPRESS OLE DB library, just make sure that,
1) The path of DLL folder under the main folder of library is in appended to the
PATH environment variable
2) The path of LIB folder under the main folder of library is in appended to the
LIB environment variable
3) The path of INCLUDE folder under the main folder of library is in appended to
the INCLUDE environment variable
GETTING STARTED
Once the library is properly installed and set up, you can use it in any project for
accessing data. In order to use the EXPRESS ODL in your project, the following three
steps are required:
#include <SypODLAll.h>
This statement will include all necessary files for using ODL. However,
SypODLAll.h header file does not declare UI classes. For those classes, you
need to add separate header file for each UI class.
2. In the View-Resource Includes option, add the following line under Compile-
Time directives
#include <SypOleDbLib.rc>
You may now try to compile the project to make sure all the files exist and are in
proper path.
Now, you are all set to use the Express ODL library.
There are two ways in which the ODL classes can be used: with exception trapping
block and without exception trapping block. The following section explains these
methods in detail.
If you want the library to catch exception and display error, use first method as shown
below.
try
{
….
statements
….
}
catch(CSypODLException& e)
{
e.DisplayError( );
}
The advantage here is that you do not need to check the HRESULT value of each
method call thereby substantially reducing the number of statements. In case if a
method fails, the control jumps to exception and the exception takes care of
processing errors.
However, in some cases, this is not a desired situation. Even if a method fails, you
would like the control to continue and not to jump to the exception. But nevertheless,
you would also like to know if a method succeeded. In this case, you can apply the
second method as shown below.
Here, you do not need the try-catch block since the exception throwing capability of a
class has been disabled. Of course, each method is returning some value to indicate if
it failed or succeeded. This is the ideal situation when you want to ignore the failure of
a method that may be less important and want to continue with other tasks regardless.
Copyright©2001. Sypram Technology. www.sypram.com
16
EXPRESS OLE DB Library: User’sGuide
m_Conn.SetProvider(“Microsoft.JET.OLEDB.4.0”);
m_Conn.Open(“C:\\Test.mdb”, “Admin”, “”);
m_Conn.SetProvider(“SQLOLEDB.1”);
m_Conn.Open(“LocalServer”, “sa”, “”, “NorthWind”);
m_Conn.SetProvider(“MSDAORA”);
dbinit.AddProperty(DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO,false);
dbinit.AddProperty(DBPROP_AUTH_USERID, OLESTR("sa"));
dbinit.AddProperty(DBPROP_INIT_DATASOURCE, OLESTR("dank500"));
dbinit.AddProperty(DBPROP_INIT_PROMPT, (short)4);
dbinit.AddProperty(DBPROP_INIT_LCID, (long)1033);
dbinit.AddProperty(DBPROP_INIT_CATALOG, OLESTR("pubs"));
m_Conn.SetProvider(“SQLOLEDB.1”);
m_Conn.Open(dbinit);
To set the connection timeout value, call SetTimeOutValue method before opening
the connection as shown below.
The SetTimeOutValue method takes one parameter of type long, which sets the
connection timeout value in seconds.
By default, OLE DB service components are included when you use any of the
overloaded Open method of CSypODLConnection class This is because this class
has a property called
m_bIncludeServiceComponents,
which is set to TRUE by default. So, in case, if you decide not to use service
components with Open method, set this property to FALSE before calling the Open
method as shown below.
Opening a recordset
EXPRESS OLE DB library provides two classes for managing recordsets. The
CSypODLRecordBase class is a template class and needs a static accessor to access
rowset data, whereas CSypODLRecordset class is internally built with dynamic
accessor. This means if you want to use the former class, you need to create a static
accessor class for every table and query you want to open. Clearly, this is somewhat
time consuming and awkward if you have several tables and queries to work with.
However, the static accessor provides an advantage of executing faster than dynamic
accessor. The choice is up to the user. In fact, CSypODLRecordBase class serves as
a base class for CSypODLRecordset class. Here, we will mostly focus on
CSypODLRecordset class as it offers several additional functionalities.
You can open a table or a query using Open method of recordset class. The format of
the Open method is specified as,
So, in order to open a table with forward-only cursor type, the above statement can be
written as
Rs.Open(“MyTable”,&m_Conn,1,SYPODL_RECORDSETTYPE_FORWARDONLY);
CSypODLConnection that should have been connected to the database. The third
parameter specifies the command type. The command types are defined in ODL as
#define SYPODL_COMMANDTYPE_TABLE 1
#define SYPODL_COMMANDTYPE_QUERY 2
So, here 1 indicates a table and 2 indicates a query (an SQL statement).
Similarly, the fourth parameter specifies the cursor type. The cursor types are defined
in ODL as
#define SYPODL_RECORDSETTYPE_FORWARDONLY 1
#define SYPODL_RECORDSETTYPE_KEYSET 2
#define SYPODL_RECORDSETTYPE_STATIC 3
#define SYPODL_RECORDSETTYPE_DYNAMIC 4
These cursor types are pretty much like ADO cursor types with very minor
differences. Refer to ADO and OLE DB documentations for further information on
cursor types.
Cursor Locations:
The rowset cursor can be created either on database server side or on client
application side. OLE DB provides facility for Client Cursor Engine, which can be
added to create a client-side cursor. EXPRESS ODL recordsets contain a property
called m_bHasClientCursor, which by default is set to TRUE. This means that
by default, the cursor is created on client-side. But if you want to create a server-side
cursor, you have to turn of this property as,
Rs.m_bHasClientCursor = false;
Rs.Open(“MyTable”, &m_Conn, 1, SYPODL_RECORDSETTYPE_KEYSET);
Once you open a recordset, the row pointer of recordset is, by default, automatically
moved to first row. This means that you need not call MoveFirst method after
opening a recordset. You may straight navigate through the recordset using
MoveNext method. The following example illustrates this.
. . . statement
MoveNext();
}
In some situations, you may want to control this behavior, meaning that you may want
to call MoveFirst yourself rather than Open method doing it. You can do this by
setting the recordset property m_bAutoMoveFirst to false before you call Open
method, as in
Rs.m_bAutoMoveFirst = false;
Rs.Open(“MyTable”, &m_Conn, 1, SYPODL_RECORDSETTYPE_KEYSET);
Rs.MoveFirst();
While(!Rs.IsEOF())
{
. . . statement
. . . statement
MoveNext();
}
Fetching data:
CString strName;
long id;
COleDateTime birthDate;
The first parameter in the method requires database column name to be passed. You
may also pass the column index instead of column name. The column index starts
with 1 for indicating first column in the table or query and so on. For fetching data
In fact, if you use a wrong variable type for extracting a column value, the method
displays an error message clearly indicating what type of variable to use.
As we mentioned before, the EXPRESS library has two classes to work with
recordsets, CSypODLRecordBase and CSypODLRecordset. The former class is
a template class that manages recordset data through a static accessor. So, you need a
static accessor for each table or query you want to manage data for. Here, we will
exclusively focus on CSypODLRecordset class since it is much easier to work
with this class. Moreover, it is more intuitive to work with this class for the reason
that it resembles very much to the ADO recordset class.
RULE : 1 - you must turn off the m_bHasClientCursor property before opening
a recordset. If you opened the recordset with custom properties, you must not set the
DBPROP_CLIENTCURSOR property.
RULE : 2 - Furthermore, you must use either forward-only or dynamic cursor in order
to perform data manipulation operations. If you use any cursor type other than these
two, you may get unpredictable errors.
Example:
Editing a record:
Example:
Rs.m_bHasClientCursor = false;
Rs.Open(sSQL, &m_Conn, 2, SYPODL_RECORDSETTYPE_FORWARDONLY);
if(!Rs.IsEOF())
Copyright©2001. Sypram Technology. www.sypram.com
23
EXPRESS OLE DB Library: User’sGuide
{
Rs.Edit();
Rs.SetFieldValue(“Name”, “New Value”);
Rs.SetData();
}
Deleting a record:
This is the simplest task of all the three. Follow the first two steps of editing a record.
Then call Delete method.
Example:
Rs.m_bHasClientCursor = false;
Rs.Open(sSQL, &m_Conn, 2, SYPODL_RECORDSETTYPE_FORWARDONLY);
if(!Rs.IsEOF())
Rs.Delete();
Managing BLOB data is a headache if you are using the raw OLE DB or using even
the consumer templates. EXPRESS OLE DB library simplifies managing of BLOB
data by providing extra class and methods for handling BLOB data. In order to
understand using BLOB data, you have to learn using CSypODLChunk class of
EXPRESS library. This class is nothing more than an implementation class for
ISequentialStream OLE DB interface. In other words, the class is used for
handling incoming and outgoing buffers. Two methods of this class are relevant here:
Read and Write. The former is used to read data buffer from the source, while the
later is used to write into it. In our case, the CSypODLChunk class is used as
described below.
In order to fetch BLOB data from the database, follow the steps mentioned below:
1. Define an object of type CSypODLChunk
2. Open a recordset
3. Call GetBLOBChunk method and pass the chunk object defined in step 1 as
a parameter.
4. Extract byte stream buffer from the chunk object using Read method.
Example:
CSypODLRecordset mRs;
CSypODLChunk mBlobChunk;
if(!mRs.IsEOF())
{
ULONG L;
CString m_DC;
In order to insert or edit BLOB data in the database, follow the steps mentioned
below:
Example:
CSypODLRecordset mRs;
CSypODLChunk mBlobChunk;
CString m_DC;
ULONG L;
mRs.m_bHasClientCursor = false;
mRs.m_bAutoMoveFirst = false;
mRs.Open("LargeText", &m_Conn, 1, 1);
if(mRs.IsEOF())
mRs.AddNew();
else
mRs.Edit();
mRs.SetFieldValue("Name", m_Name);
m_DC.ReleaseBuffer();
if(mRs.IsEOF())
mRs.Insert();
else
mRs.SetData();
In the examples above, we have used string buffer to exchange data between string
object and chunk object. However, you can use any byte stream to be used with Read
and Write methods.
Action queries are those queries that perform some database operation but do not
return any data. The SQL statements INSERT, UPDATE, DELETE are examples of
action queries.
The simplest way to execute an action query, using EXPRESS library, is to call the
Execute method of connection (CSypODLConnection) class as shown below.
CSypODLConnection mConn;
However, if you want to execute a parametric action query, you can use the ODL class
CSypODLQuery to define and set the parameters before executing the query. The
following example illustrates this.
CSypODLQuery mQry;
From the EXPRESS OLE DB point of view, stored procedures are divided into two
categories:
Example:
CSypODLCommand mCmd;
double fOutVal = 0;
if(!mCmd.IsEOF())
mCmd.GetFieldValue("Name", m_StudentName);
Stored procedures falling in the second category are similar to parametric action
queries. And as such, they can use the same class (CSypODLQuery) used by
parametric action queries.
TRANSACTIONS
There are three methods provided by CSypODLConnection class that are used for
controlling database transactions. The three methods are as follows :
These three methods are fundamentally similar to the methods of CSession class in
consumer templates. So, we will not spend more time on this. You may refer to the
documentation of OLE DB and consumer templates for further information.
CONTACT INFORMATION
Since EXPRESS OLE DB library is distributed FREE in its binary form, the only
technical support we provide at the moment is through email at the following address:
Support@SypramTech.com.
However, those users who have purchased the source code may also contact at our
technical support line or our office at :
SYPRAM TECHNOLOGY
7 Lincoln Hoghway,
Suite 222
Edison, NJ 08820. USA.
Ph : 732-205-0170.