Discussion:
ADO Connection String ändern
(zu alt für eine Antwort)
Manfred Polak
2017-10-06 00:55:41 UTC
Permalink
Moin!

In meiner kleinen Datenbankanwendung mit ADO ist bisher der Pfad zu
den Daten fest verdrahtet. Jetzt will ich das portabel machen, und zwar
soll die Datenbank gefunden werden, wenn sie im selben (beliebigen)
Verzeichnis wie das Programm ist. Meine Idee dazu war, den Connection
String mit Hilfe von ExtractFilePath(ParamStr(0)) zu modifizieren, und
das hab ich so auch als Beispiel in einem Buch gefunden. Für meine
Verhältnisse angepasst, sieht das Beispiel so aus:

procedure TForm1.FormCreate(Sender: TObject);
var pfad: string;
begin
pfad := ExtractFilePath(ParamStr(0));
DataModule2.ADOConnection1.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;'
+ 'Data Source=' + pfad + 'KnLL.mdb;Mode=Share Deny None;Jet OLEDB:System database="";'
+ 'Jet OLEDB:Registry Path="";Jet OLEDB:Database Password="lockit";Jet OLEDB:Engine Type=4;'
+ 'Jet OLEDB:Database Locking Mode=0;Jet OLEDB:Global Partial Bulk Ops=2;'
+ 'Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";'
+ 'Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;'
+ 'Jet OLEDB:Dont Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;'
+ 'Jet OLEDB:SFP=False;';
end;

Aber da bekomme ich eine Zugriffsverletzung. Wobei in dem Beispiel
im Buch alle ADO-Komponenten in Form1 liegen, bei mir dagegen sind
sie in einem Datenmodul, und in Form1 nur zwei DBGrids. Da hatte ich
natürlich die Idee, das mit TDataModule2.DataModuleCreate statt
TForm1.FormCreate zu machen, doch da bekam ich den Fehler "Der
Vorgang ist für ein geöffnetes Objekt nicht zugelassen". Heißt das, dass
die Bestandteile eines Datenmoduls vor diesem selbst erzeugt werden?

Ich hatte dann versucht, das so zu lösen:

procedure TDataModule2.DataModuleCreate(Sender: TObject);
var pfad: string;
begin
pfad := ExtractFilePath(ParamStr(0));
DataModule2.ADOConnection1.Close;
DataModule2.ADOConnection1.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;'
+ 'Data Source=' + pfad + 'KnLL.mdb;Mode=Share Deny None;Jet OLEDB:System database="";'
+ 'Jet OLEDB:Registry Path="";Jet OLEDB:Database Password="lockit";Jet OLEDB:Engine Type=4;'
+ 'Jet OLEDB:Database Locking Mode=0;Jet OLEDB:Global Partial Bulk Ops=2;'
+ 'Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";'
+ 'Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;'
+ 'Jet OLEDB:Dont Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;'
+ 'Jet OLEDB:SFP=False;';
DataModule2.ADOConnection1.Open;
end;

Doch da kam dann der Fehler "Could not find installable ISAM". Ich hab
noch zwei oder drei leicht geänderte Varianten probiert, aber immer kam
irgendeine Exception. Aber irgendwie muss das doch gehen, oder nicht?


Manfred
Martin Schade
2018-01-11 18:39:26 UTC
Permalink
Post by Manfred Polak
In meiner kleinen Datenbankanwendung mit ADO ist bisher der Pfad zu
den Daten fest verdrahtet. Jetzt will ich das portabel machen, und zwar
soll die Datenbank gefunden werden, wenn sie im selben (beliebigen)
Verzeichnis wie das Programm ist. Meine Idee dazu war, den Connection
String mit Hilfe von ExtractFilePath(ParamStr(0)) zu modifizieren, und
das hab ich so auch als Beispiel in einem Buch gefunden. Für meine
procedure TForm1.FormCreate(Sender: TObject);
var pfad: string;
begin
pfad := ExtractFilePath(ParamStr(0));
DataModule2.ADOConnection1.ConnectionString :=
'Provider=Microsoft.Jet.OLEDB.4.0;User > ID=Admin;'
+ 'Data Source=' + pfad + 'KnLL.mdb;Mode=Share Deny None;Jet
OLEDB:System database="";'
+ 'Jet OLEDB:Registry Path="";Jet OLEDB:Database Password="lockit";Jet
OLEDB:Engine Type=4;'
+ 'Jet OLEDB:Database Locking Mode=0;Jet OLEDB:Global Partial Bulk Ops=2;'
+ 'Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";'
+ 'Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt
Database=False;'
+ 'Jet OLEDB:Dont Copy Locale on Compact=False;Jet OLEDB:Compact Without
Replica > Repair=False;'
+ 'Jet OLEDB:SFP=False;';
end;
Aber da bekomme ich eine Zugriffsverletzung.
Das ist unübersichtlich; erstmal solltest Du den String in einer extra
Variablen zusammenbauen und erst, wenn er fertig ist, ihn der ADOConnection1
zuweisen.
Post by Manfred Polak
Wobei in dem Beispiel
im Buch alle ADO-Komponenten in Form1 liegen, bei mir dagegen sind
sie in einem Datenmodul, und in Form1 nur zwei DBGrids. Da hatte ich
natürlich die Idee, das mit TDataModule2.DataModuleCreate statt
TForm1.FormCreate zu machen, doch da bekam ich den Fehler "Der
Vorgang ist für ein geöffnetes Objekt nicht zugelassen". Heißt das, dass
die Bestandteile eines Datenmoduls vor diesem selbst erzeugt werden?
Ein Form initialisiert seine Bestandteile selbst, das gilt auch für ein
Datenmodul. Wenn Du das selber veranlassen willst, dann darfst Du das vorher
nicht zusammenclicken, sondern mußt es im Quelltext selber veranlassen.
Post by Manfred Polak
procedure TDataModule2.DataModuleCreate(Sender: TObject);
var pfad: string;
begin
pfad := ExtractFilePath(ParamStr(0));
DataModule2.ADOConnection1.Close;
DataModule2.ADOConnection1.ConnectionString :=
'Provider=Microsoft.Jet.OLEDB.4.0;User > ID=Admin;'
+ 'Data Source=' + pfad + 'KnLL.mdb;Mode=Share Deny None;Jet
OLEDB:System database="";'
+ 'Jet OLEDB:Registry Path="";Jet OLEDB:Database Password="lockit";Jet
OLEDB:Engine Type=4;'
+ 'Jet OLEDB:Database Locking Mode=0;Jet OLEDB:Global Partial Bulk Ops=2;'
+ 'Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";'
+ 'Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt
Database=False;'
+ 'Jet OLEDB:Dont Copy Locale on Compact=False;Jet OLEDB:Compact Without
Replica > Repair=False;'
+ 'Jet OLEDB:SFP=False;';
DataModule2.ADOConnection1.Open;
end;
Doch da kam dann der Fehler "Could not find installable ISAM". Ich hab
noch zwei oder drei leicht geänderte Varianten probiert, aber immer kam
irgendeine Exception. Aber irgendwie muss das doch gehen, oder nicht?
Du brauchst keine ADOConnection1.Close; aufzurufen; im DataModule2 darf es
noch keine ADOConnection1 geben - sie muß erst mit Create angelegt werden.

Grüße, Martin Schade
Manfred Polak
2018-01-12 00:31:24 UTC
Permalink
Post by Martin Schade
Post by Manfred Polak
In meiner kleinen Datenbankanwendung mit ADO ist bisher der Pfad zu
den Daten fest verdrahtet. Jetzt will ich das portabel machen, und zwar
soll die Datenbank gefunden werden, wenn sie im selben (beliebigen)
Verzeichnis wie das Programm ist.
Nachdem damals keiner geantwortet hat, hab ich selbst weiter probiert
und gegoogelt, und konnte das Problem dann auch bald lösen. Ich war
eh schon nah dran, und jetzt sieht es so aus:

procedure TDataModule2.DataModuleCreate(Sender: TObject);
var pfad: string;
begin
pfad := ExtractFilePath(ParamStr(0));
DataModule2.ADOConnection1.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;'
+ 'Data Source=' + pfad + 'KnLL.mdb;Mode=Share Deny None;Jet OLEDB:System database="";'
+ 'Jet OLEDB:Registry Path="";Jet OLEDB:Database Password="lockit";Jet OLEDB:Engine Type=4;'
+ 'Jet OLEDB:Database Locking Mode=0;Jet OLEDB:Global Partial Bulk Ops=2;'
+ 'Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";'
+ 'Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;'
+ 'Jet OLEDB:Don''t Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;'
+ 'Jet OLEDB:SFP=False;';
DataModule2.ADOConnection1.Open;
AdoTable1.Open;
AdoTable2.Open;
end;

Damit das so funktioniert, lasse ich Unit2 (das Datenmodul) vor Unit1 (Form1)
erzeugen, sonst gäbe es die im ersten Posting erwähnte Exception.
Post by Martin Schade
Das ist unübersichtlich; erstmal solltest Du den String in einer extra
Variablen zusammenbauen und erst, wenn er fertig ist, ihn der ADOConnection1
zuweisen.
Na ja, das macht jetzt keinen großen Unterschied. Richtig unübersichtlich
sieht es erst bei Dir mit dem Zeilenumbruch aus ... :-)
Post by Martin Schade
Post by Manfred Polak
Doch da kam dann der Fehler "Could not find installable ISAM".
Das lag nur an einem äußerst blöden Fehler von mir. Im Connection String
steht "Jet OLEDB:Don't Copy Locale on Compact=False;". Und ich Dödel
hab aus dem "Don't" in der Prozedur ein "Dont" statt "Don''t" gemacht.
Ohne diesen Fehler hätte es schon funktioniert.
Post by Martin Schade
Du brauchst keine ADOConnection1.Close; aufzurufen; im DataModule2 darf es
noch keine ADOConnection1 geben - sie muß erst mit Create angelegt werden.
Ja, das war überflüssig, aber kein kritischer Fehler. Übrigens hab ich beim
Rumprobieren und Googeln noch eine zweite und verblüffend einfache
Lösung gefunden. Wenn man im Connection String nur den Dateinamen
der Datenbank ohne Pfad angibt, findet zwar Delphi die Datenbank nicht,
aber zur Laufzeit des Programms funktioniert es trotzdem, weil dann offenbar
der JET-Treiber von sich aus im lokalen Verzeichnis des Programms nach
der DB sucht (und sie auch findet). Aber im Vergleich zu meiner Idee, die
ja jetzt auch funktioniert, ist das nur die zweitbeste Lösung.


Manfred

Loading...