expertenaustausch > comp.lang.* > comp.lang.delphi.misc

Manfred Polak (06.10.2017, 02:55)
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 (11.01.2018, 19:39)
"Manfred Polak" schrieb im Newsbeitrag
news:9254

[..]
> + '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.

> 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.

[..]
> 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 (12.01.2018, 01:31)
Martin Schade schrieb:

>"Manfred Polak" schrieb im Newsbeitrag
>news:9254
>> 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.

>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 ... :-)

>> 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.

>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
Ähnliche Themen