Copyright: Copyright 1996 by Opus Software GmbH  (13.3.96)


Table of contents

Installation and Configuration

Completing the Installation of DirectAccess

Configuration of DirectAccess

Setting up Delphi for DirectAccess

Using DirectAccess with Delphi

Using DAO in Delphi

Recommendations

Limitations of the current release of DirectAccess

Background Information

Frequently asked questions about DirectAccess

Who is Opus Software?

Trademarks

All the companies and products mentioned herein are trademarks or registered trademarks of their respective holders.


Completing the Installation of DirectAccess

You have now installed DirectAccess. Before using it, there are a number of additional steps you need to perform.

Prerequisites

Prior to using DirectAccess, you must make sure you have installed a copy of Microsoft's Data Access Objects. You might have DAO installed already if you are using Microsoft Office, Microsoft Access, Microsoft Visual Basic Professional, or Microsoft Visual C++ 4.0.

Generation of the Delphi interface file

If you want to develop DirectAccess applications yourself, you must generate a patched BDE interface file for Delphi. DirectAccess installed Patcher.exe, which will do this for you.

We do not supply this patched file directly for two reasons:

The original file is copyrighted by Borland.

Delphi's linker contains a version check mechanism. Later releases of Delphi might contain an updated BDE.DCU that would not be compatible with the patched version that we'd supply with DirectAccess.

What we do is supply a Patcher.exe, which copies and patches your own BDE.DCU file for use with DirectAccess. To setup a patched BDE.DCU with this application, proceed as follows:

From the Opus DirectAccess program group, run Delphi Interface Patcher (for BDE.dcu) (Patcher.exe).

Into the field Original BDE.DCU, type the full path and filename of your original BDE.DCU file that was supplied with Delphi. Click the ...-button to get a file-open dialog.

Example:

C:\Program Files\Borland\Delphi 2.0\Lib\BDE.DCU

Into the field Patched BDE.DCU, type the full path and filename of where the patched copy of BDE.DCU should be saved. Click the ...-button to get a file-save dialog. This file should be in a different folder than the original and it should bear the name BDE.DCU, just like the original.

Example:

C:\Program Files\Opus\DirectAccess\Lib\BDE.DCU

Note: The patched copy must be called BDE.DCU to be usable. Do not save this copy over the original file. If you do, you will not be able to compile applications for the BDE anymore.

Click OK.

The original file will be read, patched, and the patched file written to the indicated location.

Setting up Delphi to use DirectAccess

When DirectAccess is installed, you need to include it into your Delphi environment and your projects, if you want to develop DirectAccess applications. These two steps are explained in:

Setting up Delphi to use DirectAccess

Setting up your application to use DirectAccess

DirectAccess is now installed completely. To check the installation and the integration into Delphi, add a TDatabase to one of your forms and try to get the listing of alias names in the dropdown list of the AliasName property. To try a connection to a database, refer to:

Connecting to an unprotected database

For more information of what the installation process has done, refer to:

Manual installation of the DirectAccess DLL


Manual installation of the DirectAccess DLL

To setup the DirectAccess DLL yourself (e.g. in your own setup), proceed as follows:

Copy ODAPI32.dll from the installation disk to the desired location on your harddisk. The default location for the DLL is C:\Program Files\Common Files\Opus Shared\DirectAccess.

Example:

C:\Program Files\Common Files\Opus Shared\DirectAccess\ODAPI32.dll

Add the following key path to your registry: HKEY_LOCAL_MACHINE\Software\Opus\DirectAccess\ODAPI (run RegEdit on Windows 95, or RegEdt32 on Windows NT to see it).

Example:

HKEY_LOCAL_MACHINE
+ ...
+ Software
  + ...
  + Opus
    + DirectAccess
      + ODAPI
  + ...
+ ...

Add a new string value named DLLPath to the key ODAPI you just created and set the value to the path of ODAPI32.dll, which you copied earlier on.

Example:

DLLPath=C:\Program Files\Common Files\Opus Shared\DirectAccess

Note: Do not specify the name of the DLL itself at the end of the path. Supply only the path.

If you're writing a custom setup for your own DirectAccess application, these are the steps required by DirectAccess for that installation.


Configuration of DirectAccess

DirectAccess relies on the same aliasing concept that the BDE uses. To access a Jet database, you must first set up an alias to it. This alias defines the settings necessary for DirectAccess to connect to the database.

Unlike setting up an alias to a Jet database within the BDE, DirectAccess aliases are easy to control. Just add a line to the ODA.INI file, or alternatively add a key and a value to the system registry.

The advantages of using aliases are twofold:

Your application can be transparently switched between using DirectAccess and using the BDE. To make this possible, simply add the same aliases to both environments.

Your application automatically uses external configuration information to determine the location of its database files. This makes installation and configuration a lot easier. Since DirectAccess supports the system registry, your application can easily be configured differently for different users, e.g. with different default user names.

For more information, please refer to:

Using the system registry to configure DirectAccess

Using the ODA.INI file to configure DirectAccess

Options that can be defined for an alias


Using the system registry to configure DirectAccess

DirectAccess and the system registry

The system registry is a central, system-provided repository for configuration information. It is the recommended way for Win32 applications to store such information. To edit the system registry manually, use RegEdit in Windows 95, or RegEdt32 in Windows NT. To edit it programmatically, use the Windows API calls (they are prefixed with Reg...).

DirectAccess stores its configuration information in two paths in the registry. The first is for global configuration (user independent), while the second is for user-dependent configuration. The two paths are:

HKEY_LOCAL_MACHINE\Software\Opus\DirectAccess\Configuration

HKEY_CURRENT_USER\Software\Opus\DirectAccess\Configuration

The format of the information is the same for both paths. Values in the user-dependent path override respective values in the global path.

Configuring an alias in the system registry

To add a database alias to the system registry, proceed as follows:

Add the path ..\Aliases\<aliasName> to the required base path.

Example:

HKEY_LOCAL_MACHINE
+ ...
+ Software
  + ...
  + Opus
    + DirectAccess
      + Configuration
        + Aliases
          + MyAlias
  + ...
+ ...

Add a string value named Path to the above path. Then set the value to the name of your Jet database file (including the entire access path).

Example:

Path = C:\MyDatabases\MyDatabase.mdb

The examples given now define a complete alias named MyAlias to the database file C:\MyDatabases\MyDatabase.mdb.

To see what options other than Path you can define for an alias, refer to:

Options that can be defined for an alias

Advanced configuration using the system registry

This is missing.


Using the ODA.INI file to configure DirectAccess

The ODA.INI file

In addition to the system registry, DirectAccess supports configuration using an INI file. Though this is not the recommended way, it is sometimes just simpler.

Configuring an alias in the ODA.INI file

To add a database alias to the ODA.INI file, proceed as follows:

Open the ODA.INI file from within the Windows directory, or create it there if it does not yet exist.

Make sure there is a section called [Aliases], and add a line to it that defines your alias. The line is <aliasName>=<dbFilePath>.

Example:

[Aliases]
MyAlias=C:\MyDatabases\MyDatabase.mdb

If you want to define other options for this alias, proceed as follows:

Add a section called [<aliasName>], and write the options into that section, line by line.

Example:

[MyAlias]
SystemDb=C:\MyDatabases\System.mdw
User Name=Mickey

To see what options you can define for an alias, refer to:

Options that can be defined for an alias

Advanced configuration using the ODA.INI file

This is missing.


Options that can be defined for an alias

There are a number of options that can be defined for an alias. Every options consists of a name=value pair. In the system registry, the options are represented by string values, in the ODA.INI file, you just write them into the required section. The available options are given below in the form of examples.

Basic options

Path = C:\MyDatabases\MyDatabase.mdb

The Path option defines the entire filename of the Jet database file to connect to. You can alternatively use the Connect option to connect directly to data sources other than Jet databases.

Exclusive = True/False

The Exclusive option controls whether the database should be opened for exclusive access.

Read Only = True/False

The Read Only option controls whether the database should be opened for read-only access.

Security-related options

SystemDb = C:\MyDatabases\System.mdw

The SystemDb option defines the system database to use for accessing the database file (it defines the valid user accounts).

Note: You cannot use different system databases within the same session. Use multiple sessions if you need to access multiple system databases concurrently.

User Name = Mickey

The User Name option defines the default user name to use when logging on to the database. If you have the login prompt enabled on your TDatabase, this user name will be displayed as the default. If you don't specify this options, Admin is assumed.

Password = Mouse

The Password option defines the password to use when logging on to a database without a login prompt.

Note: It is generally not a good idea to store legible passwords in the configuration, as this compromises security. This option is provided for ease-of-use in environments needing little security only.

Advanced options

Lock Edits = True/False

The Lock Edits option controls whether records should be locked when the Edit method is called (DAO method), or only when the Update method is called.

DirectAccess calls Edit when you start editing a record, and Update when you post the changes. Using Lock Edits, you can control whether to use pessimistic, True, or optimistic locking, False.

Separate Workspace = True/False

The Separate Workspace option controls whether the database should be opened in a DAO workspace of its own, or whether it may share its workspace with other open databases. Workspaces are shared only between databases opened for the same user with the same password in any case.

The BDE defines transactions as being local to a single database. DAO, on the other hand, defines transactions as being local to a workspace. If you need strict adherence to the BDE definition, you must set this option to True. If not, you should leave it False, as this uses less system resources. Be aware, though, that the scope of a transaction may now span multiple databases, in violation of the BDE's normal behaviour.

Connect = dBASE III;C:\MyFiles\DBase

The Connect option allows you to connect to data sources other than Jet databases directly, ie. without having to set up a Jet database with linked tables. If you use the Connect option, you must omit the Path option.

Examples:

Connect = dBASEIII;C:\MyFiles\DBase
Connect = FoxPro 2.6;
Connect = ODBC;DATABASE=MyDb;UID=user;PWD=password;DSN=odbcname


Using DirectAccess with Delphi

Setup of DirectAccess in Delphi

Setting up Delphi to use DirectAccess

Setting up your application to use DirectAccess

Connecting to databases

Connecting to an unprotected database

Connecting to a protected database

Connecting to databases with different system databases

A note on using transactions

Using DAO directly

The DirectAccess DAO interface

Using DirectAccess DAO in Delphi

Using DAO together with DirectAccess

Recommendations

Recommendations when using DirectAccess

Bugs and limitations in this release of DirectAccess

Bugs and limitations of DirectAccess

Bugs in Microsoft DAO

DAO bug regarding transactions

DAO bug regarding inserts/deletes


Setting up Delphi to use DirectAccess

To set up the Delphi design environment to use DirectAccess instead of the BDE, proceed as follows:

Make sure you have installed the DirectAccess interface, BDE.DCU.

Start Delphi.

From the Component menu, choose Install....

Enter a new Library filename. This new file will be the library to use when you want DirectAccess integrated into Delphi's design environment.

Example:

C:\Program Files\Opus\DirectAccess\Lib\CmpLib32.dcl

In the Search Path, add the path to your DirectAccess interface, BDE.DCU, at the start.

Example:

C:\Program Files\Opus\DirectAccess\Lib;...

Note: It is important to enter the path to the DirectAccess interface before the path to the normal Delphi library. Otherwise, Delphi's original BDE.DCU will override the DirectAccess interface.

Choose OK. Delphi now recompiles your existing component library using the DirectAccess interface file. This new component library is then saved under the name you have given it. When Delphi finally loads this new library, it uses DirectAccess to access data.

Delphi's design environment now uses DirectAccess to access data whenever you load the C:\Program Files\Opus\DirectAccess\Lib\CmpLib32.dcl library. Exceptions are the database management tools such as the SQL monitor and the Database Explorer. We are not currently planning to support those tools.

To revert to using the BDE instead of DirectAccess, simply open your old component library again.

Note: Delphi now uses DirectAccess in its design environment, but applications compiled in this environment do not necessarily use DirectAccess yet. To make sure they do, refer to

Setting up your application to use DirectAccess


Setting up your application to use DirectAccess

To set up a project so it uses DirectAccess instead of the BDE, proceed as follows:

Make sure you have installed the DirectAccess interface, BDE.DCU.

Start Delphi.

Open your project.

From the Project menu, choose Options..., then tab to the page named Directories/Conditionals.

In the Search Path, add the path to your DirectAccess interface, BDE.DCU, at the start.

Example:

C:\Program Files\Opus\DirectAccess\Lib;...

Note: It is important to enter the path to the DirectAccess interface before the path to the normal Delphi library. Otherwise, Delphi's original BDE.DCU will override the DirectAccess interface.

Choose OK. The next time you recompile your application it will use DirectAccess to access data.

To revert to using the BDE instead of DirectAccess, simply remove the search path setting and recompile.

Note: At run-time, your application now uses DirectAccess to access data, but during design it does not necessarily use DirectAccess yet. To make sure it does, refer to

Setting up Delphi to use DirectAccess


Connecting to an unprotected database

Database connections from within Delphi applications are done just like with the BDE, i.e. using a TDatabase component.

To connect to an unprotected Jet database file, proceed as follows:

Setup an alias to the database file you want to connect to.

Example (in ODA.INI):

[Aliases]
MyAlias=C:\MyDatabases\MyDatabase.mdb

Start Delphi, and load your project.

Add a TDatabase component to one of your forms.

Set the AliasName property to the name of your alias, e.g. MyAlias.

Set LoginPrompt to False.

Set Connected to True. Delphi now attempts to connect to your database.


Connecting to a protected database

Besides the steps required to connect to an unprotected database, you must also define the system database (holding the user accounts) to use, and activate the login prompt.

To connect to a protected Jet database file, proceed as follows:

Setup an alias to the database file you want to connect to. Define the system database to use and, optionally, the default user name.

Example (in ODA.INI):

[Aliases]
MyAlias=C:\MyDatabases\MyDatabase.mdb

[MyAlias]
SystemDb=C:\MyDatabases\System.mdw
User Name=Mickey

Use a TDatabase component with AliasName set to the alias name you chose.

Note: DirectAccess does not support the use of different system databases within a single session. What's more, you may not change the system database once you have set it by opening any database. In short: within a given session, use only databases with the same system database.

If you need to access multiple system databases, refer to:

Connecting to databases with different system databases


Connecting to databases with different system databases

DirectAccess does not support the use of different system databases within a single session. What's more, you may not change the system database once you have set it by opening any database.

To access databases with different system databases, use a different session for each of the databases. To do this, proceed as follows:

Place a TSession component on your form, and give it a SessionName, e.g. MySession.

Place a TDatabase component on the form, give it a DatabaseName, e.g. MyDb, and set its SessionName property to the name of your session, e.g. MySession.

To access data, place a TQuery component on the form. Set its SessionName property to the name of your session, e.g. MySession, and its DatabaseName property to the name of your database connection, e.g. MyDb.

Note: It is important that you set both the DatabaseName and the SessionName property of the TQuery component. Otherwise the TQuery will try to open a database alias of the given name in the default session.

Implementation Note

Each TSession is mapped by DirectAccess to a different DAO DbEngine object (i.e. a private engine). Each of those engines can use only one particular system database during its entire lifetime. This is a restriction of DAO, not of DirectAccess.


A note on using transactions

Differences in transaction locality between DirectAccess and the BDE

The BDE defines transactions as being local to a single database. DAO, on the other hand, defines transactions as being local to a workspace. To reduce resource consumption of database connections, DirectAccess normally does not open a separate workspace for every database connection. Instead, it tries to use an existing workspace for the given user with the given password.

A transaction started on a database thus sharing a workspace with another actually extends to that other database too. This is not what the BDE would do. If you need strict adherence to the BDE definition, you must set the Separate Workspace option in your alias definition to True.

Please read the following topic too:

DAO bug regarding transactions


The DirectAccess DAO interface

DirectAccess replaces the BDE with direct calls to DAO to access the Jet engine. You can also use DAO directly from within your programs.

For better performance, DirectAccess does not talk to DAO by means of Delphi's OLE automation capabilities. We have written a wrapper around the DAO class framework so that calls are bound at compile-time, not run-time. The performance is about 5 times better that way. It is still possible to get a proper Delphi OLE automation object from any of DirectAccess's DAO objects. This interface is not the direct map of the OLE interface. It is a wrapper around the OLE interface that makes DAO more accessible from within Delphi. What it does is the following:

Outgoing variants are converted to suit DAO. Incoming variants are converted to suit Delphi.

Outgoing Delphi long strings are converted to the OLE BStr type. Incoming BStr data is converted to Delphi long strings.

DAO's bookmarks are of type PSafeArray. The DAO unit converts them to true variants for use in Delphi. Delphi then handles deallocation automatically.

Errors returned by the OLE interface are trapped and converted to an exception.

There is a couple of units defining this interface, DAO.dcu, DAO_Base.dcu, and DAO_OLE.dcu, that are supplied with DirectAccess . The files DAO.int, DAOClass.inc, DAOConst.inc, and DAOErr.inc, define the interface in source form.

To install the DAO interface, simply copy these files to your harddisk, and include the path to them into your project search path.

For information on how to program with DAO in Delphi, refer to:

Using DirectAccess DAO in Delphi

Using DAO together with DirectAccess

Using Delphi OLE automation with DirectAccess DAO

Bugs in Microsoft DAO


Using DirectAccess DAO in Delphi

Programming with DirectAccess DAO in Delphi is very much the same as using it in Microsoft Access, or in Visual C++ 4.0, with the following exceptions:

You must free allocated objects yourself.

You cannot simply omit optional arguments.

The engine is not created at startup.

Freeing allocated objects

There is a simple, yet effective, technique for doing this in a standard way. Simply take every object you retrieve into a with..try statement, and close it with finally Free end.

Example:

with DAO.CreateEngine{} do try
  with Workspaces do try
    with Item[0] do try
      ...
    finally Free end;
  finally Free end;
finally Free end;

Be aware in particular that the collections (Workspaces, Fields, Errors, etc.) are objects too and must be freed.

Omitting optional arguments

Because the DAO interface supplied with DirectAccess is bound at compile-time, you cannot omit optional arguments to methods. Instead, write a _ in place of omitted arguments. The _ is an initialized constant exported by the DAO unit supplied with DirectAccess.

Example: With Delphi's OLE automation, you would write

rs:= db.OpenRecordset( 'Select * from Bla' );

With the early-bound DAO interface, you have to write

rs:= db.OpenRecordset( 'Select * from Bla', _, _ );

This is because the method declaration looks like this:

function OpenRecordset( const name: string; const _type, options: Variant ): DAORecordset;

Creating an engine

Unlike Microsoft Access, the DAO unit does not create the DbEngine object by default. To get an engine, use either of

eng:= DAO.CreateEngine{};

eng:= DAO.CreatePrivateEngine{};

The former initially creates a new engine object for your application. On subsequent calls it simply returns the same object again (with an increased reference count). The latter creates a new OLE engine object every time it is called. DirectAccess uses the latter call to create new engines for every BDE session so it can use a different system database for each session.


Using DAO together with DirectAccess

Sometimes you may wish to do something to a cursor, or a database, that only DAO lets you do effectively. For this reason, you can coerce a BDE object to its equivalent DAO object as follows:

TSession.Handle corresponds to DAOEngine

TDatabase.Handle corresponds to DAODatabase

TQuery.StmtHandle corresponds to DAOQueryDef (often temporarily allocated)

TQuery.Handle corresponds to DAORecordset

For all these objects, the UserData property defined by the DAO unit for every DAO object is reserved for use by DirectAccess.

Example:

with DAORecordset(MyQuery.Handle) do begin
  FindFirst( 'TheField = "Hello world!"' );
end;
MyQuery.Resync( [] );

Note the use of Resync to refresh the cursor's buffers after moving the current record yourself.


Using Delphi OLE automation with DirectAccess DAO

As said before, DirectAccess supplies a wrapper around the DAO class framework that is more efficient than Delphi's generic OLE automation calls. If you still want to use Delphi's mechanism, you can do so easily. All you need is to call the AsVariant method of any DirectAccess DAO object to get a proper Delphi OLE automation object for it.

Example:

thisRS:= DAORecordset(MyQuery.Handle).AsVariant;
clonedRS:= thisRS.Clone;  // this is Delphi OLE automation now!
clonedRS.FindFirst( 'TheField = "Hello world!"' );
ShowMessage( 'The field value is ' + clonedRS['TheField'] );

The same example, not using Delphi's OLE automation, would look like this:

with DAORecordset(MyQuery.Handle).Clone{} do try
  FindFirst( 'TheField = "Hello world!"' );
  with Fields do try
    with Item['TheField'] do try
      ShowMessage( 'The field value is ' + Value );
    finally Free end;
  finally Free end;
finally Free end;

This is clearly quite a pain, and in the above example, I would prefer the OLE automation method. But don't forget, it's fast. So if stepping through a 5000 record table and calling MoveNext and EOF on every iteration, I should think again.


Bugs in Microsoft's DAO

During development of DirectAccess, we have found a number of bugs (or at least instances of very peculiar behaviour) in Microsoft's DAO. These bugs are reproducible using either Microsoft Visual C++ 4.0 or Microsoft Access 95 (we did not always test both environments).

We have notified Microsoft of these bugs on CompuServe. There has been no response yet.

DAO bug regarding transactions

The problem occurs with the following call sequence:

rs1:= db.OpenRecordset(...);
rs2:= db.OpenRecordset(...);
db.BeginTrans;
rs1.Edit;
  rs2.Free;
  rs2:= db.OpenRecordset(...);
rs1.Update;
db.CommitTrans;

Upon the call to rs1.Update, DAO fails saying that we never called Edit or AddNew, as we should have. Clearly, this is not so. Besides, the EditMode of rs1 rightly (or wrongly now?) says dbEditInProgress just prior to the call to Update.

While this code sequence may seem esoteric at first, it is actually quite common in DirectAccess. It occurs when using linked TQueries to build one-to-many forms. The recordset rs1 is the main query, rs2 is the child query. After calling Edit on a record of the main query, rs1, Delphi rebuilds the child query, rs2, because the Edit operation might have refreshed the main record contents.

How does this affect you? Simply put, don't use transactions on one-to-many forms, or, to be precise, using linked queries.

DAO bug regarding inserts/deletes

The problem occurs with the following sequence of operations:

Open a dynaset.

Browse a little and fetch some data.

Delete a record.

Insert a new record.

Set Bookmark to LastModified.

According to the documentation, the new record should be added to the end of the recordset. It is not, at least with our table (containing about 4000 rows).

How does this affect you? If you delete a record from a cursor, and subsequently insert another record into that cursor, it might not appear at the end of the cursor, but at a random location.

We have tried to remedy the problem by requerying the recordset after an insert. This does not work properly as bookmarks are not stable across requeries.


Recommendations when using DirectAccess

This is a list of recommendations that will help you get the most out of DirectAccess.

Convert your databases to the new Jet 3.0 format.

Use double instead of single for floating point values. There is a rounding bug when converting single to double on the Intel Pentium CPU. To fix this, we convert the values via the string representation, which is rather slow.

Select only the fields you need in a query. Every field you select is read immediately whenever the VCL accesses a row (except for blobs). This may slow down data access significantly.


Limitations of the current release of DirectAccess

This first release of DirectAccess has a number of limitations. With every limitation noted you will find the planned release that will fix it.

Limitations regarding data access (TQuery, TTable)

Limitations regarding data-aware components

Limitations in the design environment

In addition, there is a known bug in this beta:

Don't use a DatabaseName that is the name of a DirectAccess alias, other than the alias you are connecting to. If you do, the alias you name in DatabaseName will be overwritten by the settings for this connection.

Example:

[Aliases]
MyAlias=C:\MyDatabases\MyDatabase.mdb
MyOtherAlias=C:\MyDatabases\MyOtherDatabase.mdb

Don't use a TDatabase object with the following settings (for example):

AliasName = MyAlias

DatabaseName = MyOtherAlias


Limitations regarding data access (TQuery, TTable)

Data access limitations can be separated into three different areas:

Results processing

SQL-based data access (SQL queries)

ISAM-based data access (tables and indexes)

Limitations of results processing

Blobs are always read entirely into memory, regardless of the requested chunk. This will be fixed in the next release.

The single floating point type suffers from rounding errors. The BDE does not know the single type, so DirectAccess converts singles to doubles. It seems that the Intel Pentium CPU does not convert singles to doubles excactly. To fix this problem, we have resorted to converting first to a string representation, and then back to a double. This is, of course, slow.

Cached updates are not supported.

Limitations for SQL-based data access

Stored procedures (stored, parametrized queries in Jet) are not supported. This will be fixed in the next release.

Blob-type parameters are not supported (fields are). We have not yet determined when this will be fixed.

Limitations for ISAM-based data access

TTable does not support filtering yet. This will be fixed in the next release.

TTable does not fully support ranges yet (used in master/child relationships). In particular, string keys are compared with case sensitivity. This will be fixed in the first release.

TTable index seeks (GotoNearest, Lookups) do not support partial keys yet. This will be fixed in the first release.


Limitations regarding data-aware components

Standard components

TStoredProc is not supported.

TBatchMove is not supported.

TUpdateSQL is not supported (mainly because cached updates are not yet supported).

Third-party components

No problems have been reported so far.


Limitations in the design environment

Within Delphi's design environment, the following limitations apply:

The Database Explorer as a stand-alone tool is not supported. The integrated explorer in Delphi's design environment might be supported in the future. This will be fixed in an upcoming release.

The Query Builder is not supported. We have not yet determined when this will be fixed.


Frequently asked questions about DirectAccess

This is a short summary of key information about DirectAccess. For a more complete treatise, please refer to other parts of this document.

Is DirectAccess faster than the BDE against Jet databases?

DirectAccess is significantly faster in many cases and never slower. In addition, many operations that are impossible with the BDE can be done with DirectAccess, for instance index access.

Is DirectAccess difficult to install?

End user installation is easy. All it requires is the installation of DAO and a single additional DLL. The only other thing you need to do is to add a key to the registry. To distribute DAO, you need a distribution license. This license is included with the Access Development Toolkit, with Visual C++ 4.0, and with Visual Basic 4.0 Professional.

Is DirectAccess difficult to administer?

Not at all. To setup a DirectAccess alias definition for an unprotected database, it suffices to add a single registry entry, or alternatively a single line to the ODA.INI file. For protected databases, you just need to add a few more entries or lines to indicate the system database to use.

Will all components work with DirectAccess?

All standard Delphi data-aware components work with DirectAccess. Most third-party components should work as well, especially if they do not access the BDE directly but rather rely on Delphi's data access classes.

Can DirectAccess be integrated into Delphi's design environment?

Yes. A simple library recompilation integrates DirectAccess into Delphi's design environment.

Can I run applications using the BDE in parallel with DirectAccess applications?

Yes. DirectAccess replaces the BDE only for applications compiled explicitly for DirectAccess. Other applications are not affected.

You can even use the BDE in your Delphi design environment but compile the application for DirectAccess, or vice versa. This requires you to set up identical aliases in both environments.

Does DirectAccess support all of Delphi's functionality?

No. Some of the new features are not yet supported. Those are:

-	Delayed (cached) updates

-	Database Explorer

-	Query Builder

-	Schema repository

Others will not be supported. Amongst those are:

-	ReportSmith (use ODBC to access Jet from ReportSmith)

-	SQL Monitor

Can I use the BDE in parallel with DirectAccess to access data sources other than Jet?

Not at present. You can, though, use Jet itself to access other data sources than Jet databases. Given the need, DirectAccess could support a BDE pass-through in the future.

Does DirectAccess run on Windows 95 and Windows NT?

Yes, it runs on Windows 95 and Windows NT 3.51 or higher. These are precisely the platforms supported by Delphi 2.0.

Does DirectAccess run on Windows 3.xx?

No, it does not, not even with Win32s installed. Microsoft's Data Access   Objects, the foundation of DirectAccess, are not available for 16-bit platforms. There is neither a 16-bit version nor one running under Win32s.

Does DirectAccess work with Delphi 1.0?

No, it does not. DirectAccess is a 32-bit product targeted at Delphi 2.0.

Is DirectAccess thread-safe?

Not really. Microsoft's Data Access Objects, the foundation of DirectAccess, can only be used from within the main thread of an application. Using it from within other threads is an error. Thread-safety is thus not an issue. In addition, Borland's code that calls the BDE automatically serializes BDE calls. Since DirectAccess is called by the same code, it is serialized too. You may still NOT access data from any other than the main thread using DirectAccess.


About Opus Software GmbH

Opus Software GmbH is the company that develops DirectAccess. What follows is a short profile of the company and some of its customers.

About our customers and products

About Opus Software GmbH

Who are our customers and what are our products?

Our company is specialized in desktop and client/server database applications. We support other software development companies with expert advice and by developing complex components, or entire applications, according to their needs. In addition, we have written a number of specialized applications in Microsoft Access, ranging from automated graphical catalogue generation to the analysis of host data.

To give you a little more insight into our work, we would like to introduce to you two of our customers:

One of our customers is Traviswiss, a subsidiary of the well known Swiss airline, Swissair, and a leading seller of computer solutions for travel agencies. For Traviswiss we compose expert opinions and develop software prototypes to help Traviswiss make the shift from their existing mainframe solution to client/server technology.

Another customer is Abacus, the Swiss market leader in business software. For Abacus we develop highly specialized Delphi software components, and support their Delphi development team, to help Abacus launch their next generation solutions on time.

Being both a consultant and a developer, we have gained a wide experience of both implementation issues and customer wishes. Combining this experience with our own requirements makes it clear that Delphi is still lacking a number of powerful, yet easy to use components in different areas. We are developing some of them. Opus not being a marketing company, these components are distributed by Philog AG. Please contact Roland Strauss for questions and orders.

CompuServe:	100034,3165

Phone:	0041 (0)56 634 31 41

Fax:	0041 (0)56 634 31 51

Postal:	Philog AG
Roland Strauss
Eggflurstrasse 3
8917 Unterlunkhofen

What is Opus Software GmbH?

Opus Software GmbH is a Swiss software development company. It consists of four partners supported occasionally by freelancers. Opus is also part of a network of partner companies sharing know-how and resources.

We have extensive knowledge of database and operating system technologies. On the one hand, this allows us to develop efficient data access components for both ISAM and SQL-based database engines. On the other hand, our experience with the Windows operating environment enables us to write sophisticated visual user-interface components. The sum of which make for a more productive software development environment.

1995 we finished our second successful year, and we would enjoy being of service to you in our following ones.

For further technical questions please contact one of our software engineers, Peter Arrenbrecht, Remo von Ballmoos, and Daniel Wyss. Or contact Toni Steimle for general questions.

e-mail:	opussoftware@access.ch

CompuServe:	101560,2152

Phone:	0041 (0)1 930 76 36

Fax:	0041 (0)1 930 34 10

Postal:	Opus Software GmbH
Im Kratten 32
CH-8623 Wetzikon
Switzerland


What are the Data Access Objects?

Data Access Objects (DAO for short) is Microsoft's new native interface to the Jet database engine (and possibly other databases in the future). DAO is a set of OLE classes that are a one-to-one image of the data access classes found in Microsoft Access 7.0. Since it represents the new 32-bit Jet engine, DAO is only available on the 32-bit platforms Windows 95 and Windows NT 3.5 or higher.

To give you a more precise idea of the interface DAO presents, the following depicts the root of the DAO class hierarchy:

DbEngine
  Workspaces
  Databases
    Tables
      FieldDefs
      Indexes
    QueryDefs
    Recordsets
      Fields
      ...

DAO is the most direct and complete interface to Jet currently available. It makes both SQL-based and ISAM-based access available. There is one caveat to keep in mind when using it though: DAO is not threadable, i.e. only the main thread of an application is allowed to call DAO functions.


What is the Jet database engine?

The Microsoft Jet database engine is the database engine used by Microsoft Access, Microsoft Visual Basic, and other applications. It is a fast, versatile and very easily manageable multi-user database engine for desktop applications with no more than about 20 active users. Jet is not a database server, but a client database engine that can access files on a server concurrently with other Jet engines to support multiple users. Jet is mainly a SQL engine, but it also allows direct ISAM access to data.

Jet can also access other data sources transparently, e.g. SQL Server, Btrieve, dBase, any ODBC data source, and others. As such, Jet can also be regarded as a data access layer unifying access to a variety of data sources.

Starting with Visual C++ 4.0, Microsoft began shipping Data Access Objects, a native OLE API to the Jet engine.


What is the Borland Database Engine?

The Borland Database Engine is a data access layer similar in concept to ODBC, and also Jet. It unifies access to a variety of different data sources, amongst them many SQL servers, dBase, Paradox, and ODBC data sources.

Placed initially as a contender against Microsoft's ODBC in the battle for the general database API standard, it now plays a role only in Borland's own applications, namely Delphi, dBase, and Paradox. This is not to say its design is inferior, only that it does seem to have lost the battle. Its design is, in fact, better than that of the purely SQL-based ODBC when used to access ISAM databases because it does, in constrast to ODBC, support direct index and table access. Given the market impact of Delphi, the battle might even have erupted again. The BDE still has a grave problem, though, since nobody but Borland seems to be implementing native BDE drivers for new databases engines. In addition, the BDE's use of ODBC data sources is not very efficient.

Microsoft has also released a next generation database API, namely the OLE-based Data Access Objects class hierarchy. Currently this API is available only for the Jet database engine, out of which it evolved.


What is ODBC?

ODBC stands for Open DataBase Connectivity, the database standard touted by Microsoft. It is a layer unifying access to a variety of data sources and enjoys widespread support from both database system and application development tool vendors. Nearly every serious database engine has an ODBC driver.

ODBC is purely SQL-based. This is to say that it does not allow direct access to indexes or physical record locations, like ISAM-based layers do. In addition, drivers can (and are allowed to) vary greatly in their functionality. It is somewhat like ODBC provides consistent naming for database functions, but does not guarantee you can use them. While it's possible to query for a driver's supported functions, it is difficult to write fully generic yet still efficient ODBC applications because of all the different constellations it has to adapt to.


What is SQL?

SQL stands for Structured Query Language. Initially designed by IBM to be a uniform database query and manipulation language, it has evolved into a form making it suitable also for writing state-of-the-art desktop database applications. SQL focuses on client/server performance optimization and programmer productivity. This in contrast to ISAM which focuses on top notch local performance, at the expense of programming time.

SQL is ideal for client/server processing because complex data queries or updates can be processed entirely by the server. This reduces network traffic and fully exploits the strengths of the server. SQL relieves the programmer because oft repeated standard data management tasks can now be formulated in simple SQL queries rather than coding them for the n-th time. Also, SQL servers automatically determine which indexes to use for fast data access and can even adapt to changing conditions. On the other hand, things not accounted for in the design of SQL are hard to accomplish, for instance handling recursive data structures. Old standars of SQL are also not very suitable for the design of modern interactive desktop applications.

Popular SQL servers are Sybase SQL Server, Oracle RDB, Watcom SQL Server (recently renamed Sybase SQL Anywhere), Microsoft SQL Server. There are also a number of client SQL engines, for instance Microsoft Jet, and Watcom SQL Client Engine.


What is ISAM?

ISAM stands for Index Sequential Access Method. This term denotes direct table access using indexes to lookup key values. Popular examples of database systems using this paradigm are Btrieve, dBase, Paradox, FoxPro, Clipper, etc. ISAM allows for very fast database applications at the expense of programming time, when compared to SQL. Some systems allow both paradigms, for instance Microsoft's Jet engine, and recently also Btrieve. Most SQL database systems use ISAM-techniques internally.

While ISAM systems typically use client based engines, there are also some server solutions. Btrieve is one.