Board index » delphi » Reopening/changing DB at runtime

Reopening/changing DB at runtime


2003-10-21 11:27:55 PM
delphi140
I want to provide for the user changing their active database at runtime.
The code first closes the active database then displays the initial screen
where the user can select another (or the same) database and a passwort
(if applicable). Then the databse is being opened (and I know it IS open
since I can query any field's contents or any table's recordcount) but I
get no display in any of my DB components (DBGrid, DBEdit etc.). Using D7
with Access 2000 backend.
Here are the relevant parts of various methods:
Closing database:
grdTablePerson1024.DataController.DataSource := nil; //disconnects grid
(I'm using DevExpress' QuantumGrid but have tried with ordinary DBGrid to
no avail, and there are also ordinary components like DBEdit etc. that too
don't display anything)
... Similar code as above for the other grids
for i := 0 to frmDM.ComponentCount - 1 do
begin
if frmDM.Components[i] is TADOTable then
with TADOTable(frmDM.Components[i]) do
begin
DisableControls;
Close;
end;
if frmDM.Components[i] is TADOQuery then
with TADOQuery(frmDM.Components[i]) do
begin
DisableControls;
Close;
end;
if frmDM.Components[i] is TDataSource then
with TDAtaSource(frmDM.Components[i]) do
begin
DataSet.DisableControls;
Enabled := false;
end;
end;
Now the user selects another (or the same) database.
Open database:
with frmDM do
begin
if ADOConn.Connected then
ADOConn.Connected := false;
ADOConn.ConnectionString := strDataSource;
ADOConn.Connected := true;
end;
if frmDM.Components[i] is TADOTable then
with TADOTable(frmDM.Components[i]) do
begin
Open;
EnableControls;
end;
if frmDM.Components[i] is TDataSource then
with TDataSource(frmDM.Components[i]) do
begin
Enabled := true;
DataSet.EnableControls;
end;
//the following is from a separate function that is called for each
prepared TADOQuery - Query is the parameter
with Query do
begin
Active := true;
EnableControls;
end; //end of procedure
if grdTablePerson1024.DataController.DataSource = nil then //connects
grid
grdTablePerson1024.DataController.DataSource := frmDM.dsrPerson;
... Similar code for the other grids
I've also tried it with Refresh but again that didn't change anything.
Any ideas?
TIA.
Brigitte
 
 

Re:Reopening/changing DB at runtime

"Brigitte Spatz" <XXXX@XXXXX.COM>schrieb im Newsbeitrag
Quote
I want to provide for the user changing their active database at runtime.
The code first closes the active database then displays the initial screen
where the user can select another (or the same) database and a passwort
(if applicable). Then the databse is being opened (and I know it IS open
since I can query any field's contents or any table's recordcount) but I
get no display in any of my DB components (DBGrid, DBEdit etc.). Using D7
with Access 2000 backend.
1.) save all Items from ADOConnection.Datasets into a
TComponentList Object (SavedADOdatasets)
2.) close ADO Connection
3.) set new ConnectionString
4.) open ADO Connection
5.) Open all datasets in the saved list:
for i:=0 to SavedADOdatasets.Count-1 do
TCustomADODataSet(SaveADOdatasets.Items[i]).Open;
6.) Free the TComponentList (SavedADOdatasets)
hth
Andreas
 

Re:Reopening/changing DB at runtime

Check that TADOTable and TADOQuery are connected to ADOConn using Connection
property, they should not have their connection string.
Why do you change connection string inside cycle (for i := 0 to
frmDM.ComponentCount - 1)?
TADOTable and TADOQuery inherit from TCustomADODataSet, so you may write
if Components[i] is TCustomADODataSet then (Components[i] as
TCustomADODataSet).Close();
or even
if Components[i] is TDataSet then (Components[i] as TDataSet).Close();
DisableControls/EnableControls is not needed.
//----------------------
Regards,
Viatcheslav V. Vassiliev
www.oledbdirect.com
The fastest way to access MS SQL Server,
MS Jet (Access) and Interbase (through OLEDB)
"Brigitte Spatz" <XXXX@XXXXX.COM>???????/???????? ?
???????? ?????????: news:oprxefwtkk8p7c4k@localhost...
Quote
I want to provide for the user changing their active database at runtime.
The code first closes the active database then displays the initial screen
where the user can select another (or the same) database and a passwort
(if applicable). Then the databse is being opened (and I know it IS open
since I can query any field's contents or any table's recordcount) but I
get no display in any of my DB components (DBGrid, DBEdit etc.). Using D7
with Access 2000 backend.

Here are the relevant parts of various methods:

Closing database:
grdTablePerson1024.DataController.DataSource := nil; //disconnects grid
(I'm using DevExpress' QuantumGrid but have tried with ordinary DBGrid to
no avail, and there are also ordinary components like DBEdit etc. that too
don't display anything)
... Similar code as above for the other grids
for i := 0 to frmDM.ComponentCount - 1 do
begin
if frmDM.Components[i] is TADOTable then
with TADOTable(frmDM.Components[i]) do
begin
DisableControls;
Close;
end;
if frmDM.Components[i] is TADOQuery then
with TADOQuery(frmDM.Components[i]) do
begin
DisableControls;
Close;
end;
if frmDM.Components[i] is TDataSource then
with TDAtaSource(frmDM.Components[i]) do
begin
DataSet.DisableControls;
Enabled := false;
end;
end;
Now the user selects another (or the same) database.
Open database:
with frmDM do
begin
if ADOConn.Connected then
ADOConn.Connected := false;
ADOConn.ConnectionString := strDataSource;
ADOConn.Connected := true;
end;
if frmDM.Components[i] is TADOTable then
with TADOTable(frmDM.Components[i]) do
begin
Open;
EnableControls;
end;
if frmDM.Components[i] is TDataSource then
with TDataSource(frmDM.Components[i]) do
begin
Enabled := true;
DataSet.EnableControls;
end;
//the following is from a separate function that is called for each
prepared TADOQuery - Query is the parameter
with Query do
begin
Active := true;
EnableControls;
end; //end of procedure
if grdTablePerson1024.DataController.DataSource = nil then //connects
grid
grdTablePerson1024.DataController.DataSource := frmDM.dsrPerson;
... Similar code for the other grids

I've also tried it with Refresh but again that didn't change anything.

Any ideas?

TIA.

Brigitte
 

Re:Reopening/changing DB at runtime

On Tue, 21 Oct 2003 21:35:04 +0400, Viatcheslav V. Vassiliev
<XXXX@XXXXX.COM>writes:
Quote
Check that TADOTable and TADOQuery are connected to ADOConn using
Connection
property, they should not have their connection string.
They don't. Only ADOConn has a connection string and all others are
connected to ADOCOnn.
Quote
Why do you change connection string inside cycle (for i := 0 to
frmDM.ComponentCount - 1)?
I don't. You must have misread something.
Brigitte
 

Re:Reopening/changing DB at runtime

On Tue, 21 Oct 2003 19:22:06 +0200, Andreas Schmidt
<XXXX@XXXXX.COM>writes:
Quote
1.) save all Items from ADOConnection.Datasets into a
TComponentList Object (SavedADOdatasets)

2.) close ADO Connection

3.) set new ConnectionString

4.) open ADO Connection

5.) Open all datasets in the saved list:

for i:=0 to SavedADOdatasets.Count-1 do
TCustomADODataSet(SaveADOdatasets.Items[i]).Open;
Can't do that since there are several queries that don't have their
SQLString property set as they're used ad hoc. (Otherwise I would need to have
several dozen more TADOQueries.)
Quote
6.) Free the TComponentList (SavedADOdatasets)
But in the end this isn't really different to what I am doing now - I mean
the order of things and which commands are executed are all the same - all
you do differently is iterate through the tables and queries as part of a
list rather than singly but that really can not make a difference as to
whether the table contents is being displayed on screen or not.
Brigitte
 

Re:Reopening/changing DB at runtime

"Brigitte Spatz" <XXXX@XXXXX.COM>schrieb im Newsbeitrag
Quote
On Tue, 21 Oct 2003 19:22:06 +0200, Andreas Schmidt
<XXXX@XXXXX.COM>writes:

>1.) save all Items from ADOConnection.Datasets into a
>TComponentList Object (SavedADOdatasets)
Note: this list includes only *active* queries or tables.
Closes queries/tables are not included.
The Online Help says:
" property DataSets[Index: Integer]: TCustomADODataSet
Description
Use DataSets to access active datasets associated with a connection
component.
An active dataset is one that is currently open."
Quote
>2.) close ADO Connection
>
>3.) set new ConnectionString
>
>4.) open ADO Connection
>
>5.) Open all datasets in the saved list:
>
>for i:=0 to SavedADOdatasets.Count-1 do
>TCustomADODataSet(SaveADOdatasets.Items[i]).Open;

Can't do that since there are several queries that don't have their
SQLString property set as they're used ad hoc. (Otherwise I would need to have
several dozen more TADOQueries.)
This for...do loop opens only these ADOQueries/tables that were active
before you've changed the ADOConnection.
Quote
>6.) Free the TComponentList (SavedADOdatasets)

But in the end this isn't really different to what I am doing now - I mean
the order of things and which commands are executed are all the same - all
you do differently is iterate through the tables and queries as part of a
list rather than singly but that really can not make a difference as to
whether the table contents is being displayed on screen or not.
My algorythm works like this:
- remind all *open* ADODataset
- change the ADOConnection
- reopen all ADODatasets from the stored list
This is a straight forward approach.
It doesn't change any datasesitive control.
Don't use DisableControl or EnableControl in your code
because it is useless and dangerous[1] in this context!
Your code is a example how not to use DisableControl/EnableControl.
[1] if you call DisableControl twice and EnableControl once
all related datasesitive controls will never refresh till the end
of your app.
If you call DisableControl you must use a
try ...finally clause:
ds.DisableControl;
try
// modify several hundred records
finally
ds.EnableControl;
end;
If you simply close and open a dataset the methods
DisableControl/EnableControl should *not* be called.
hth
Andreas
 

Re:Reopening/changing DB at runtime

On Tue, 21 Oct 2003 19:22:06 +0200, Andreas Schmidt
<XXXX@XXXXX.COM>writes:
Quote
1.) save all Items from ADOConnection.Datasets into a
TComponentList Object (SavedADOdatasets)

2.) close ADO Connection

3.) set new ConnectionString

4.) open ADO Connection

5.) Open all datasets in the saved list:

for i:=0 to SavedADOdatasets.Count-1 do
TCustomADODataSet(SaveADOdatasets.Items[i]).Open;

6.) Free the TComponentList (SavedADOdatasets)
Have now tried this approach but am getting a Stack Overflow during step
5. I have also tried closing the datasets before setting the new
connection string but the Stack Overflow remained.
Any ideas?
TIA.
Brigitte