Search code examples
multithreadingdelphidelphi-xe2dbexpress

DBX Error: Driver could not be properly initialized when use OmniThreadLibrary (but ok otherwise)


I need to make a long running task in the background. I'm using OmniThreadLibrary hopping this could help me.

I use dbexpress+mssql driver. I can connect ok when is in the main thread, but get:

Project Project1.exe raised exception class TDBXError with message 'DBX Error: Driver could not be properly initialized. Client library may be missing, not installed properly, of the wrong version, or the driver may be missing from the system path.'.

The connections are created in each thread, not shared datamodule:

type
  TdbManager = class(TObject)
  private
    { private declarations }
    FCon: TSQLConnection;
  public
    { public declarations }
    procedure Open(Driver:String; aparams:TStringList);overload;
    procedure Close;

    constructor Create;
    destructor Destroy;override;
  end;

  constructor TdbManager.Create;
begin
  inherited Create;
  FCon := TSQLConnection.Create(nil);
end;

procedure TdbManager.Open(Driver: String; aparams: TStringList);
var
  i: Integer;
  key:string;
begin
  FCon.DriverName := Driver;

  for i := 0 to params.Count - 1 do
  begin
    key := params.Names[i];
    FCon.Params.Values[key] := params.Values[key];
  end;

  LogMsg('Open DB '+ Driver + ': ' + FHost + '\' + FDatabase);

  FCon.Open;
  LogMsg('Done.');
end;

And the background task is executed:

procedure TBackupPlan.OnScheduleTrigger(Sender: TScheduledEvent);
begin
  Parallel.Async(procedure
  begin
    ExecuteDataTask( Sender.Name );
  end);
end;

procedure TBackupPlan.ExecuteDataTask(const Name: String);
var
  db:TdbManager;
begin
  db := nil;

  db := TSqlServerManager.Create;
  db.Open(self.Driver, options);

  result := db;
end;

If I execute this directly, open ok. If I use Parallel.Async then get the error. What is happend here?


Solution

  • I found information about this here:

    http://docwiki.embarcadero.com/RADStudio/en/DbExpress_Database_Specific_Information

    MSSQL Driver Requires Calls to CoInitialize and CoUninitialize for Console Applications and Worker Threads

    The MSSQL driver does not call CoInitialize or CoUninitialize. Earlier versions of the MSSQL driver, which is a COM driver, called CoInitialize and CoUninitialize directly, which is not a good practice. VCL applications take care of these calls for you, so VCL applications do not require calling CoInitialize and CoUninitialize. However, applications using the MSSQL driver in console applications or in worker threads need to call CoInitialize/CoUninitialize. If this call is not made, you will see the following error message: "DBX Error: Driver could not be properly initialized. Client library may be missing, not installed properly, of the wrong version, or the driver may be missing from the system path." For help on CoInitialize, see the CoInitialize Function on MSDN.