Newsgroup: it.comp.lang.delphi
Titolo: Portabilità per ADO

Salve a tutti! Ho un altro problema :(. Sto facendo un programma
database con delphi utilizzando ADO. Ho bisogno che la mia
applicazione sia portabile, funzionante su qualsiasi pc. Il problema è
che ado x connettersi al database ha bisogno del percorso del database
a design-time, e questo x quello che devo fare io non va bene. O,
potrebbe anche andare bene, l'importante è che riesca a trovare una
soluzione. Ho provato anche con una path relativa, ma non funziona
come vorrei. Come posso fare? :(

simoneap...@hotmail.it
 presented the following explanation :

Non è vero che serve un percorso a design time.
Creati una o due voci di registro (non hai detto che databse stai 
utilizzando), e crea la stringa di connessione a runtime.
Per esempio se utilizzi SQLServer qualcosa del genere:
AdoConnection1.ConnectionString := 
Format('Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security 
Info=False;Initial Catalog=%s;Data Source=%s', [ACatalog, ADatabase]);

utilizzando), e crea la stringa di connessione a runtime.
A che pro le voci di registro ?

a design-time
Dove lo hai letto ?
Puoi benissimo impostare la ConnectionString a run-time.

 ha scritto nel messaggio 
news:1172488319.3...@j27g2000cwj.googlegroups.com...

Hai due strade:
1. con il wizard della connectionstring di ADOConnection generi la stringa 
di connessione, la salvi.
Apri la connessione di ADOConn, in questo modo la stringa si completa 
automaticamente, copi la stringa di connessione (la fai diventare blu di 
selezione e Ctrl+C).
A questo punto cancelli dall'object inspector la stringa di selezione, vai 
nel medodo onCreate della tua form che, spero, sia un datamodule, e 
all'interno, ti prendi  il path della cartella in cui è l'eseguibile con un 
bel Getfilepath(application.exename) (attenzione che nei Datamodule 
l'oggetto application non è richiamato nelle unit user di default), ci 
aggiungi il nome del tuo database poi, in un bel try  .. except ...end 
definisci per ADOConnection.connectionstring la tua stringa di connessione 
incollando la stringa di connessione che avevi precedentemente salvato e 
inserendo al posto giusto il path appena ricavato.
In questo modo la trasportabilità è sempre garantita.
2. con wordpad generi e chiudi un file vuoto di testo all'interno della 
certella eseguibile, campi l'estensione di tale file di testo da .TXT a 
.udl, doppio clik sul file rinominato e compare il wizard per definire la 
conessione per ADO. Nota che si può fare senza delphi.
Da delphi, all'interno dell'oggetto ADOConnection nella stringa di 
connessione metti, anzichè il collegamento con il database, il collegamento 
al file .udl.
In questa maniera hai la possibiltà di cambiere, il ogni momento, al di 
fuori del tuo programma, il collegamento al database 

bel Getfilepath(application.exename)
La funzione è ExtractFilePath.  In ogni caso, secondo me, questa non è
la strada ideale e, volendo evitare il file UDL esterno, si può
ricorrere a una terza via, che a mio avviso è sempre la migliore, in
quanto consente di uniformare le opzioni di configurazione
dell'applicazione in un unico file: il file .INI.
Nel file INI è possibile inserire la ConnectionString, in modo da
poterla modificare al volo, se si vuole accedere non necessariamente
al DB che accompagna l'applicazione, ma a un DB su un'altra macchina.

 
simoneappugli...@hotmail.it
 presented the following explanation :

Ringrazio tutti x aver accolto il mio grido di aiuto! :) Ho risolto
con il consiglio di massimo pini(GRAZIE!!!)
il codice è questo
procedure TForm1.FormCreate(Sender: TObject);
  var Pathdb : string;
  begin
    Pathdb := ExtractFilePath(Application.ExeName)+'Database\db1.mdb';
 
adoconnection1.ConnectionString:=Format('Provider=Microsoft.Jet.OLEDB.
4.0;Mode=ReadWrite;Persist Security Info=False;Data Source=%s',
[pathdb]);
    adoconnection1.Connected:=true;
    adotable1.Active:=true;
  end;
funziona perfettamente!
Ora un'ultima cosa...avete presente la finestra che appare quando ci
si connette al database? Quella con id e password...ogni volta che
avvio il programma mi appare e io non la voglio. come si toglie?
grazie ancora!

avvio il programma mi appare e io non la voglio. come si toglie?
Devi impostare la proprietà LoginPrompt dell'ADODatabase a false.

Andrea Laforgia formulated the question :

E perché no? :)
Usare il registro, usare un file ini, poco importa, il concetto era sul 
fatto che si potesse parametrizzare la stringa di connessione.

 dell'impossibilità di connettersi, nel caso.
Scusa l'ignoranza...ma se non scrivo quei controlli sull'OnCreate
della form dove devo scriverli?
non è il primo evento quando avvio l'applicazione? (sono alle prime
armi, penso si noti! :))

E perché no? :)
Perché io sono dell'idea che meno si tocca il registro di Windows
meglio č.

della form dove devo scriverli?
Nel sorgente del progetto (Project->View source).
Anche perché facendo come fai si ha il bruttissimo effetto di far
"flashare" la form principale (appare e scompare velocemente in caso
di eccezione).  Invece, la cosa migliore è effetturare tutti i
controlli alla partenza dell'applicazione, ancora prima di creare la
form principale.

Nel sorgente del progetto (Project->View source).
p.s.: io uso sempre una classe Configuration di tipo Singleton, che
istanzio e carico alla partenza dell'applicazione, nel sorgente del
progetto.  La classe sostanzialmente ha i metodi GetInstance() e
ReleaseInstance() (per l'allocazione e il rilascio) e i metodi Load()
e Save() a cui passo il nome del file .INI.  Espone, poi, come
proprietą, tutte le opzioni del file .INI.  In questo modo, da
qualsiasi parte dell'applicazione, riesco comodamente ad accedere alla
configurazione.

 configurazione.
Ti ringrazio dei consigli, mi saranno molto utili!
probabilmente mi vedrai ancora qui in giro a chiedere aiuto x qualche
mistero irrisolto! :)
ci sentiamo, grazie ancora!

 al DB che accompagna l'applicazione, ma a un DB su un'altra macchina.
Sono daccordo nel rivalutare i file INI
Quello che volevo evidenziare è che vi sono una serie di metodi per generare 
in modo semiautomatico la connectionstring 

 meglio è.
Assolutamente daccordo 

 configurazione.
Mi preparo per l'impilazione....
....siccome la cosa mi interessa molto, è possibile avere due righette
di esempio?
Grazie mille

di esempio?
Scrivo il seguente codice, senza averlo testato un granché, ma ti dà
l'idea di massima.  Supponendo di avere la classe che gestisce la
configurazione:
unit Configuration;
interface
type
  TConfiguration = class
  private
    FIniFileName: string;
    FMyProperty: Integer;
  public
    property IniFileName: string read FIniFileName write FIniFileName;
    property MyProperty: Integer read FMyProperty write FMyProperty;
    class function GetInstance: TConfiguration;
    class procedure ReleaseInstance;
    procedure Load;
    procedure Save;
  end;
implementation
uses SysUtils, IniFiles;
var
  SingleInstance: TConfiguration = nil;
  ReferenceCount: Integer = 0;
{ TConfiguration }
class function TConfiguration.GetInstance: TConfiguration;
begin
  if not Assigned(SingleInstance) then
    SingleInstance := TConfiguration.Create;
  Inc(ReferenceCount);
  Result := SingleInstance
end;
class procedure TConfiguration.ReleaseInstance;
begin
  if ReferenceCount>0 then
  begin
    Dec(ReferenceCount);
    if ReferenceCount = 0 then
      FreeAndNil(SingleInstance);
  end;
end;
procedure TConfiguration.Load;
begin
  if not FileExists(FIniFileName) then
    raise Exception.Create(ClassName+'.Load(): ini file does not
exist!');
  with TIniFile.Create(FIniFileName) do
    try
      FMyProperty := ReadInteger('MAIN', 'MyProperty', 0);
    finally
      Free;
    end;
end;
procedure TConfiguration.Save;
begin
  with TIniFile.Create(FIniFileName) do
    try
      WriteInteger('MAIN', 'MyProperty', FMyProperty);
    finally
      Free;
    end;
end;
end.
Come puoi vedere è un singleton che legge il file .ini dal contenuto
seguente:
[MAIN]
MyProperty=3234
Ora, nel sorgente di progetto, avrò qualcosa del tipo:
program Project1;
uses
  Forms,
  SysUtils,
  Unit1 in 'Unit1.pas' {Form1},
  Configuration in 'Configuration.pas';
{$R *.res}
var
  AppConf: TConfiguration;
begin
  Application.Initialize;
  AppConf := TConfiguration.GetInstance;
  try
    AppConf.IniFileName := ChangeFileExt(Application.ExeName, '.ini');
    AppConf.Load; // carico la configurazione
    Application.CreateForm(TForm1, Form1);
    Application.Run;
    AppConf.Save; // salvo eventuali cambiamenti alla configurazione
  finally
    AppConf.ReleaseInstance;
  end;
end.
E sulla form principale, ad esempio:
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
  Dialogs, StdCtrls, Configuration;
type
  TForm1 = class(TForm)
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    FConfiguration: TConfiguration;
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
  FConfiguration := TConfiguration.GetInstance;
  Edit1.Text := IntToStr(FConfiguration.MyProperty);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
  FConfiguration.ReleaseInstance;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FConfiguration.MyProperty := StrToInt(Edit1.Text);
end;
end.
Tutto qui :-)

 Tutto qui :-)
Alla faccia del tutto qui :-(
Mi sento un troglodita con la mazza!!!
Ti ringrazio per lo spunto, adesso mi metto a studiare (tempo
permettendo) il tuo codice.
GRAZIE MILLE!!!
Vittorio