Reputation: 13
I use Delphi XE7, and one of our large legacy applications still uses the BDE extensively with Paradox tables. I know the BDE is deprecated, but we have no choice with this app.
This app currently sets up the BDE aliases at run time, at startup. It uses the standard default Session provided by the BDE, and it uses "TSession.AddStandardAlias" to add an alias, and refers to many tables defined in data modules.
I now have the need to be able to change the folder path an alias refers to later in the running of the app, but have found problems with it. Basically, it seems to work, but after the alias is changed it somehow still refers to the previous path. Even "TSession.GetAliasParams" reports the new path, but then an error occurs in Bde.DBTables because it's trying to access the previous path, which no longer exists.
Given the app is large, I've reproduced a similar problem in the following sample project. If someone is willing to try this, it's a very simple app with just the main form. You need to setup two folders, and drop any Paradox table into one folder, when then specify that path to that folder in the Edit box and then press the "Set Alias Path" button, that will set the alias, and then it writes to a label below the button that tells you the path the alias refers to. Then the "Find table" button and edit box looks for the existence of a table using "TSession.GetTableNames".
The simplest way to do it is to setup two folders "C:\TEMP\testBDE\path1" and "C:\TEMP\testBDE\path2", and drop any Paradox table into path1, when you run the app press the "Set Alias Path" button, and then press the "Find table" button and it will report the table exists.
Then change the alias to refer to path2, which is empty, and it reports it pointing path2, but also reports the table exists. It's easy then to move the table from path1 to path2, and it will then report the table does not exist.
Any advice would be greatly appreciated.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
Button2: TButton;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
Bde.DBTables;
const
myAlias = 'ALIAS1';
function getPathFromAlias(tempAlais : String ): String;
var
MyStringList : TStringList;
i, k: integer;
tempStr, newDirectory: String;
begin
newDirectory:='';
MyStringList := TStringList.Create;
try
Session.GetAliasParams(tempAlais,MyStringList);
{ fill stringlist with driver names }
for i := 0 to MyStringList.count-1 do
begin
tempStr:= uppercase(trim(MyStringList.Strings[i]));
k := pos('PATH=', tempStr);
if k > 0 then
begin
delete(tempStr,1, k+4);
newDirectory:=tempStr;
end;
end;
finally
MyStringList.Free;
end;
result:=newDirectory;
end;
procedure setAliases( apath : String);
var
MyStringList : TStringList;
begin
(*
MyStringList := TStringList.Create;
try
MyStringList.Add( 'PATH='+apath);
MyStringList.Add( 'ENABLE BCD=FALSE');
MyStringList.Add( 'DEFAULT DRIVER=PARADOX');
Session.ConfigMode := cmSession;
if Session.IsAlias( myAlias) then
Session.ModifyAlias( myAlias, MyStringList)
else
Session.AddStandardAlias( myAlias, apath, 'PARADOX');
Session.ConfigMode := cmSession;
finally
MyStringList.Free;
end;
*)
Session.ConfigMode := cmSession;
if Session.IsAlias( myAlias) then
Session.DeleteAlias( myAlias);
Session.AddStandardAlias( myAlias, apath, 'PARADOX');
Session.ConfigMode := cmSession;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
setAliases( Edit1.Text);
Label1.Caption := getPathFromAlias( myAlias);
end;
function TableExists(const aDataBaseName, aTableName:string): Boolean;
var
TableNames: TStringList;
begin
TableNames:=TStringList.Create;
try
Session.GetTableNames(aDatabaseName,'',True,False,TableNames);
Result:=(TableNames.IndexOf(aTableName)<>-1);
finally
TableNames.Free;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
temps : String;
myTable : TTable;
begin
if TableExists( myAlias, Edit2.Text) then
Label2.Caption := 'Exists'
else
Label2.Caption := 'Not found'
end;
end.
Upvotes: 1
Views: 1609
Reputation: 23046
You need to Close the session before changing the alias properties and then Open it again afterward:
procedure TForm1.Button1Click(Sender: TObject);
begin
Session.Close;
setAliases( Edit1.Text);
Label1.Caption := getPathFromAlias( myAlias);
Session.Open;
end;
The problem is not that path changes are not recognised but that such changes are not recognised if they are made to aliases that are in use as this scenario in your test program illustrates:
i.e. if the first thing you do is change the path, then the alias does indeed reflect that changed path. The issue is that once you have used an alias, changes to the path are not subsequently reflected.
By closing the session and re-opening it, you ensure that the alias is properly "reset".
In your actual application this may cause knock-on effects with database connections needing to be re-opened after closing and re-opening the session, although this is speculation on my part.
As an alternative to closing the session in order to modify an alias at runtime, another approach might be to add a new alias with the required properties and redirect the database connections to that alternate alias.
This also will obviously entail disconnecting and reconnecting all databases and queries that are redirected to this alternate alias.
Upvotes: 1