Skip to content

InstantADO ​

ActiveX Data Objects (ADO) broker for multiple database engines.

Overview ​

The InstantADO unit provides database persistence using Microsoft's ActiveX Data Objects (ADO), enabling access to various databases through OLE DB providers.

Supported Databases:

  • Microsoft SQL Server
  • Microsoft Access (Jet/ACE)
  • Oracle
  • MySQL
  • IBM DB2
  • Any database with an OLE DB provider

Key Features:

  • Universal ADO interface for multiple databases
  • ADOX-based or SQL-based database building
  • Database compaction (MS Access)
  • Navigational and SQL broker implementations
  • Transaction support (provider-dependent)
  • Connection string based configuration

Note: For new projects, consider InstantFireDAC which provides better performance and modern architecture.

Key Classes ​

TInstantADOConnectionDef ​

Connection definition for ADO broker.

Properties ​

PropertyTypeDescription
ConnectionStringstringADO connection string or link file path
LinkFileNamestringPath to .udl file (Universal Data Link)

Methods ​

CreateConnection ​
pascal
function CreateConnection(AOwner: TComponent): TCustomConnection; override;

Creates TADOConnection from connection string or .udl file.

TInstantADOConnector ​

Main connector component for ADO.

Inheritance:

TComponent → TInstantConnector → TInstantConnectionBasedConnector → TInstantADOConnector

Properties ​

PropertyTypeDescription
ConnectionTADOConnectionADO connection component
ProviderTypeTInstantADOProviderTypeDetected database provider type (read-only)
CanTransactionBooleanWhether provider supports transactions (read-only)

Methods ​

BuildDatabase ​
pascal
procedure BuildDatabase(Scheme: TInstantScheme;
  BuildMethod: TInstantADOBuildMethod); overload;

Builds database using specified method:

  • bmDefault: Choose automatically (ADOX for Access, SQL for SQL Server)
  • bmADOX: Use ADOX (ActiveX Data Objects Extensions) COM objects
  • bmSQL: Use SQL DDL statements
CompactDatabase ​
pascal
procedure CompactDatabase;

Compacts MS Access database file to reduce size and improve performance.

Only works with MS Jet/ACE providers.

GetProviderType ​
pascal
function GetProviderType: TInstantADOProviderType;

Detects database provider from connection string. Returns:

  • ptMSJet - Microsoft Access (Jet/ACE)
  • ptMSSQLServer - Microsoft SQL Server
  • ptOracle - Oracle
  • ptMySQL - MySQL
  • ptIBMDB2 - IBM DB2
  • ptUnknown - Other provider

Broker Classes ​

TInstantADOBroker ​

Base navigational broker for ADO (used for MS Access).

Inheritance:

TInstantBroker → TInstantRelationalBroker → TInstantADOBroker

Uses navigational access with TDataSet operations.

TInstantADOMSJetBroker ​

Specialized broker for Microsoft Access (Jet/ACE).

Inheritance:

TInstantBroker → TInstantRelationalBroker → TInstantADOBroker → TInstantADOMSJetBroker

Features:

  • Navigational dataset-based access
  • ADOX-based database building
  • Database compaction support

TInstantADOMSSQLBroker ​

SQL broker for Microsoft SQL Server.

Inheritance:

TInstantBroker → TInstantSQLBroker → TInstantADOMSSQLBroker

Features:

  • SQL-based parameterized queries
  • Custom SQL generator for SQL Server
  • BIT type for booleans
DataTypeToColumnType ​
pascal
function DataTypeToColumnType(DataType: TInstantDataType; Size: Integer): string; override;

SQL Server Data Type Mapping:

pascal
dtInteger   → INTEGER
dtFloat     → FLOAT
dtCurrency  → MONEY
dtBoolean   → BIT
dtString    → VARCHAR(n)
dtMemo      → TEXT
dtDateTime  → DATETIME
dtBlob      → IMAGE
dtDate      → DATETIME
dtTime      → DATETIME
dtEnum      → INTEGER

Resolver Classes ​

TInstantADOResolver ​

Base resolver for navigational access.

Inheritance:

TInstantCustomResolver → TInstantResolver → TInstantADOResolver

Uses TADODataSet for navigation-based operations.

TInstantADOMSJetResolver ​

Specialized resolver for MS Access with enhanced error handling.

TInstantADOMSSQLResolver ​

SQL-based resolver for MS SQL Server.

Inheritance:

TInstantCustomResolver → TInstantSQLResolver → TInstantADOMSSQLResolver

Query Classes ​

TInstantADOQuery ​

Query class for navigational brokers.

Inheritance:

TInstantQuery → TInstantRelationalQuery → TInstantADOQuery

Uses TADOQuery internally.

TInstantADOMSSQLQuery ​

SQL query class for MS SQL Server.

Inheritance:

TInstantQuery → TInstantSQLQuery → TInstantADOMSSQLQuery

SQL Generator ​

TInstantADOMSSQLGenerator ​

Custom SQL generator for MS SQL Server.

Inheritance:

TInstantSQLGenerator → TInstantADOMSSQLGenerator

Custom SQL generation:

  • ALTER COLUMN syntax
  • DROP COLUMN syntax
  • DROP INDEX with table name

Types and Constants ​

TInstantADOProviderType ​

pascal
type
  TInstantADOProviderType = (ptUnknown, ptMSJet, ptMSSQLServer, ptOracle, ptMySQL, ptIBMDB2);

TInstantADOBuildMethod ​

pascal
type
  TInstantADOBuildMethod = (bmDefault, bmADOX, bmSQL);

Build methods:

  • bmDefault: Automatic selection
  • bmADOX: Use ADOX COM objects (recommended for Access)
  • bmSQL: Use SQL DDL (recommended for SQL Server)

Usage Patterns ​

Basic Setup - MS SQL Server ​

Design-time configuration:

pascal
// 1. Drop TADOConnection on form
ADOConnection1.ConnectionString :=
  'Provider=SQLOLEDB.1;' +
  'Data Source=localhost;' +
  'Initial Catalog=MyDatabase;' +
  'Integrated Security=SSPI';
ADOConnection1.LoginPrompt := False;

// 2. Drop TInstantADOConnector on form
InstantADOConnector1.Connection := ADOConnection1;
InstantADOConnector1.Connected := True;

Basic Setup - MS Access ​

pascal
// 1. Drop TADOConnection on form
ADOConnection1.ConnectionString :=
  'Provider=Microsoft.ACE.OLEDB.12.0;' +
  'Data Source=C:\Data\MyDatabase.accdb;' +
  'Persist Security Info=False';
ADOConnection1.LoginPrompt := False;

// 2. Drop TInstantADOConnector on form
InstantADOConnector1.Connection := ADOConnection1;
InstantADOConnector1.Connected := True;

Programmatic Connection - SQL Server ​

pascal
uses
  InstantADO, Data.Win.ADODB;

procedure ConnectToSQLServer(const Server, Database: string);
var
  Connection: TADOConnection;
  Connector: TInstantADOConnector;
begin
  Connection := TADOConnection.Create(nil);
  Connection.ConnectionString := Format(
    'Provider=SQLOLEDB.1;' +
    'Data Source=%s;' +
    'Initial Catalog=%s;' +
    'Integrated Security=SSPI',
    [Server, Database]);
  Connection.LoginPrompt := False;

  Connector := TInstantADOConnector.Create(nil);
  Connector.Connection := Connection;
  Connector.IsDefault := True;
  Connector.Connected := True;

  ShowMessage(Format('Connected to %s on %s', [Database, Server]));
end;

Programmatic Connection - MS Access ​

pascal
procedure ConnectToAccess(const DatabasePath: string);
var
  Connection: TADOConnection;
  Connector: TInstantADOConnector;
begin
  Connection := TADOConnection.Create(nil);
  Connection.ConnectionString := Format(
    'Provider=Microsoft.ACE.OLEDB.12.0;' +
    'Data Source=%s;' +
    'Persist Security Info=False',
    [DatabasePath]);
  Connection.LoginPrompt := False;

  Connector := TInstantADOConnector.Create(nil);
  Connector.Connection := Connection;
  Connector.IsDefault := True;
  Connector.Connected := True;

  ShowMessage('Connected to ' + DatabasePath);
end;

Using Connection Definition ​

pascal
procedure ConnectViaConnectionDef;
var
  ConnDef: TInstantADOConnectionDef;
  Connector: TInstantADOConnector;
begin
  ConnDef := TInstantADOConnectionDef.Create(nil);
  try
    ConnDef.ConnectionString :=
      'Provider=SQLOLEDB.1;' +
      'Data Source=localhost;' +
      'Initial Catalog=MyDatabase;' +
      'Integrated Security=SSPI';

    Connector := TInstantADOConnector.Create(nil);
    try
      Connector.ConnectionDef := ConnDef;
      Connector.IsDefault := True;
      Connector.Connected := True;

      // Use connector...
    finally
      Connector.Free;
    end;
  finally
    ConnDef.Free;
  end;
end;

Using UDL File ​

pascal
// 1. Create .udl file using Windows Data Link Properties dialog
// 2. Use FILE NAME= prefix in connection string

procedure ConnectViaUDL(const UDLPath: string);
var
  Connection: TADOConnection;
  Connector: TInstantADOConnector;
begin
  Connection := TADOConnection.Create(nil);
  Connection.ConnectionString := 'FILE NAME=' + UDLPath;
  Connection.LoginPrompt := False;

  Connector := TInstantADOConnector.Create(nil);
  Connector.Connection := Connection;
  Connector.Connected := True;
end;

Building Database with ADOX (Access) ​

pascal
procedure BuildAccessDatabase(const DatabasePath: string;
  Model: TInstantModel);
var
  Connection: TADOConnection;
  Connector: TInstantADOConnector;
  Scheme: TInstantScheme;
begin
  Connection := TADOConnection.Create(nil);
  try
    Connection.ConnectionString := Format(
      'Provider=Microsoft.ACE.OLEDB.12.0;' +
      'Data Source=%s',
      [DatabasePath]);

    Connector := TInstantADOConnector.Create(nil);
    try
      Connector.Connection := Connection;

      Scheme := Connector.CreateScheme(Model);
      try
        // Use ADOX method for Access
        Connector.BuildDatabase(Scheme, bmADOX);
        ShowMessage('Database created: ' + DatabasePath);
      finally
        Scheme.Free;
      end;
    finally
      Connector.Free;
    end;
  finally
    Connection.Free;
  end;
end;

Building Database with SQL (SQL Server) ​

pascal
procedure BuildSQLServerDatabase(Connector: TInstantADOConnector;
  Model: TInstantModel);
var
  Scheme: TInstantScheme;
begin
  Connector.Connect;

  Scheme := Connector.CreateScheme(Model);
  try
    // Use SQL method for SQL Server
    Connector.BuildDatabase(Scheme, bmSQL);
    ShowMessage('Database created successfully');
  finally
    Scheme.Free;
  end;
end;

Compacting MS Access Database ​

pascal
procedure CompactAccessDatabase(Connector: TInstantADOConnector);
var
  SizeBefore, SizeAfter: Int64;
  DatabaseFile: string;
begin
  // Only works with MS Access
  if Connector.ProviderType <> ptMSJet then
    raise Exception.Create('Compact only supported for MS Access');

  DatabaseFile := Connector.DatabaseName;

  Connector.Disconnect;
  try
    SizeBefore := GetFileSize(DatabaseFile);

    // Compact database
    Connector.CompactDatabase;

    SizeAfter := GetFileSize(DatabaseFile);
    ShowMessage(Format('Database compacted: %d KB → %d KB',
      [SizeBefore div 1024, SizeAfter div 1024]));
  finally
    Connector.Connect;
  end;
end;

Detecting Provider Type ​

pascal
procedure ShowProviderInfo(Connector: TInstantADOConnector);
var
  ProviderName: string;
begin
  case Connector.ProviderType of
    ptMSJet:        ProviderName := 'Microsoft Access';
    ptMSSQLServer:  ProviderName := 'Microsoft SQL Server';
    ptOracle:       ProviderName := 'Oracle';
    ptMySQL:        ProviderName := 'MySQL';
    ptIBMDB2:       ProviderName := 'IBM DB2';
  else
    ProviderName := 'Unknown';
  end;

  ShowMessage(Format('Connected to: %s' + sLineBreak +
                    'Transactions: %s',
    [ProviderName, BoolToStr(Connector.CanTransaction, True)]));
end;

Transaction Management ​

pascal
procedure PerformTransactionalOperation;
begin
  // Check if provider supports transactions
  if not InstantADOConnector1.CanTransaction then
    raise Exception.Create('Provider does not support transactions');

  InstantADOConnector1.StartTransaction;
  try
    // Perform operations
    Obj1.Store;
    Obj2.Store;
    Obj3.Delete;

    InstantADOConnector1.CommitTransaction;
  except
    InstantADOConnector1.RollbackTransaction;
    raise;
  end;
end;

Connection Strings ​

MS SQL Server ​

Windows Authentication:

Provider=SQLOLEDB.1;Data Source=localhost;Initial Catalog=MyDB;Integrated Security=SSPI

SQL Server Authentication:

Provider=SQLOLEDB.1;Data Source=localhost;Initial Catalog=MyDB;User ID=sa;Password=mypass

SQL Server Native Client:

Provider=SQLNCLI11;Server=localhost;Database=MyDB;Trusted_Connection=yes

MS Access ​

Access 2007-2019 (.accdb):

Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Data\MyDB.accdb;Persist Security Info=False

Access 97-2003 (.mdb):

Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\MyDB.mdb;Persist Security Info=False

With Password:

Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Data\MyDB.accdb;Jet OLEDB:Database Password=mypass

Oracle ​

Provider=OraOLEDB.Oracle;Data Source=MyOracleDB;User Id=myUsername;Password=myPassword

MySQL ​

Provider=MySQLProv;Data Source=localhost;User Id=root;Password=mypass;Database=mydb

IBM DB2 ​

Provider=IBMDADB2;Data Source=MyDB2;User ID=myuser;Password=mypass

Best Practices ​

1. Use Appropriate Build Method ​

pascal
// MS Access: Use ADOX
Connector.BuildDatabase(Scheme, bmADOX);

// SQL Server: Use SQL
Connector.BuildDatabase(Scheme, bmSQL);

// Unknown: Use Default
Connector.BuildDatabase(Scheme, bmDefault);

2. Compact Access Databases Regularly ​

pascal
// Schedule compaction weekly/monthly
if Connector.ProviderType = ptMSJet then
begin
  Connector.Disconnect;
  try
    Connector.CompactDatabase;
  finally
    Connector.Connect;
  end;
end;

3. Check Transaction Support ​

pascal
if Connector.CanTransaction then
begin
  // Use transactions
  Connector.StartTransaction;
  try
    // Operations
    Connector.CommitTransaction;
  except
    Connector.RollbackTransaction;
    raise;
  end;
end
else
begin
  // Provider doesn't support transactions
  // Operations execute immediately
end;

4. Use Connection Pooling ​

pascal
// Enable connection pooling in connection string
Connection.ConnectionString :=
  'Provider=SQLOLEDB.1;Data Source=localhost;Initial Catalog=MyDB;' +
  'Integrated Security=SSPI;OLE DB Services=-2';  // Enable pooling

5. Set LoginPrompt to False ​

pascal
Connection.LoginPrompt := False;
// Prevents modal dialog on connection failure

6. Use Integrated Security for SQL Server ​

pascal
// Windows Authentication (recommended)
Connection.ConnectionString :=
  'Provider=SQLOLEDB.1;Data Source=localhost;Initial Catalog=MyDB;Integrated Security=SSPI';

7. Close Connections Properly ​

pascal
try
  // Use connector
finally
  Connector.Disconnect;
  Connection.Free;
end;

Troubleshooting ​

"Provider cannot be found" ​

Problem: ADO error -2147467259.

Solutions:

  • Install Microsoft Access Database Engine (for ACE provider)
  • Use correct provider name in connection string
  • Check 32-bit vs 64-bit provider availability

"Cannot open database" ​

Problem: Access denied or file not found.

Solutions:

pascal
// Check file exists
if not FileExists(DatabasePath) then
  ShowMessage('Database file not found: ' + DatabasePath);

// Check file permissions
// Ensure write access for .accdb/.mdb files

Transaction Not Supported ​

Problem: Provider doesn't support transactions.

Solution:

pascal
if not Connector.CanTransaction then
  ShowMessage('Warning: Provider does not support transactions');

Compact Database Fails ​

Problem: CompactDatabase raises exception.

Cause: Only works with MS Jet/ACE providers.

Solution:

pascal
if Connector.ProviderType <> ptMSJet then
  raise Exception.Create('Compact only available for MS Access');

Connection String Format Error ​

Problem: Invalid connection string.

Solution:

pascal
// Use connection string builder or .udl file
// Test connection string with ADO Test Tool

32-bit vs 64-bit Provider Mismatch ​

Problem: Provider not found in 64-bit application.

Solutions:

  • Install 64-bit Access Database Engine
  • Or compile application as 32-bit
  • Or use different provider (SQL Server Native Client)

Access Database Locked ​

Problem: "Could not use ''; file already in use".

Solution:

pascal
// Close all connections
Connector.Disconnect;

// Delete .ldb lock file
DeleteFile(ChangeFileExt(DatabasePath, '.ldb'));

Performance Optimization ​

1. Use SQL Broker for SQL Server ​

pascal
// TInstantADOMSSQLBroker is faster than navigational TInstantADOMSJetBroker
// Automatically selected for SQL Server

2. Enable Connection Pooling ​

pascal
Connection.ConnectionString := ConnectionString + ';OLE DB Services=-2';

3. Use Prepared Statements ​

pascal
// Queries automatically use prepared statements via TADOQuery

4. Set Cursor Location ​

pascal
Connection.CursorLocation := clUseClient;  // For read-only queries
// OR
Connection.CursorLocation := clUseServer;  // For updates

5. Compact Access Databases ​

pascal
// Regular compaction improves performance
Connector.CompactDatabase;

Limitations ​

MS Access Limitations ​

  1. File size limit: 2 GB
  2. Concurrent users: ~10-15 users max (performance degrades)
  3. No stored procedures: Limited server-side logic
  4. Database bloat: Requires regular compaction

Provider Limitations ​

  1. Transaction support: Provider-dependent
  2. Data type support: Varies by provider
  3. Performance: Slower than native APIs

ADO Limitations ​

  1. Windows only: ADO not available on Linux/macOS
  2. 32/64-bit mismatch: Provider bitness must match application
  3. COM dependencies: Requires Windows COM infrastructure

Migration Path ​

From ADO to FireDAC ​

pascal
// ADO (old)
uses InstantADO;
Connector := TInstantADOConnector.Create(nil);
Connector.Connection.ConnectionString := '...';

// FireDAC (new, recommended)
uses InstantFireDAC;
Connector := TInstantFireDACConnector.Create(nil);
Connector.Connection.Params.Text := ConvertADOConnectionString(...);

Benefits of migrating to FireDAC:

  • Better performance
  • Cross-platform support (Windows, Linux, macOS)
  • More databases supported
  • Modern architecture

See Also ​

Source Code ​

File: InstantADO.pasLocation: Source/Brokers/ADO/

Summary ​

The InstantADO broker provides database persistence using Microsoft's ADO technology, supporting multiple databases through OLE DB providers.

Key Features:

  • Multiple database support (SQL Server, Access, Oracle, MySQL, DB2)
  • ADOX or SQL-based database building
  • Database compaction for MS Access
  • Navigational and SQL broker implementations

Best for:

  • Legacy Windows applications using ADO
  • Microsoft Access databases
  • SQL Server applications (with limitations)

Limitations:

  • Windows only
  • Slower than native providers
  • 32/64-bit provider dependencies
  • Limited transaction support (provider-dependent)

Recommendation: For new projects, use InstantFireDAC which provides better performance, cross-platform support, and modern architecture.

Data Types (SQL Server):

  • Booleans → BIT
  • Strings → VARCHAR(n)
  • Memo → TEXT
  • Currency → MONEY
  • Blob → IMAGE
  • DateTime → DATETIME

Released under Mozilla License, Version 2.0.