Delphi FireDAC连接远程Firebird时误开本地FDB,如何创建远程数据库?
问题
使用Delphi 12.2 Enterprise搭配FireDAC和Firebird 2.5,通过以下代码连接数据库:
type TFD3Base = class(TDataModule) dbConn: TFDConnection; private FDBHost: String; FDBName: String; FPooled: Boolean; FLastError: String; FConDefName: String; {...} public //connects to the specified database procedure Connect(const AHost, AFDB: String); //create our tables if they don't exist procedure CreateTables; {...} end; procedure TFD3Base.Connect(const AHost, AFDB: String); var oDef: IFDStanConnectionDef; oParams: TFDPhysFBConnectionDefParams; begin //clear our datamodule's internal vars FLastError := ''; FDBHost := AHost; FDBName := AFDB; FConDefName := 'BWPMgr_1'; //if we're already connected, drop it if dbConn.Connected then begin dbConn.Connected := False; try FDManager.CloseConnectionDef(FConDefName); except end; end; //does our definition exist? oDef := FDManager.ConnectionDefs.FindConnectionDef(FConDefName); if not Assigned(oDef) then begin //no; create it oDef := FDManager.ConnectionDefs.AddConnectionDef; oDef.Name := FConDefName; //build params oParams := TFDPhysFBConnectionDefParams(oDef.Params); with oParams do begin DriverID := 'FB'; Protocol := ipTCPIP; Server := FDBHost; Database := FDBName; UserName := 'sysdba'; Password := 'masterkey'; OpenMode := omOpenOrCreate; end; //apply the changes oDef.MarkPersistent; oDef.Apply; end; //connect to the FDB if we can try dbConn.ConnectionDefName := FConDefName; dbConn.Params.Pooled := FPooled; dbConn.Connected := True; except on E:Exception do begin //save the error msg and re-raise FLastError := E.Message; raise; end; end; //if we get here, we're connected; create tables as needed CreateTables; {...} end;
FDManager已配置为不自动加载,程序启动时会清空所有连接定义。
本地连接时(Server设为localhost,Database设为本地路径),FDB不存在时会自动创建并打开,一切正常。但连接VPN网络中的远程Firebird 2.5服务器时(Server设为远程机器IP,Database设为该机器的本地路径,且与本地路径同名),程序未在远程机器创建FDB,反而打开了本地已存在的FDB。
需要实现:连接远程FDB,若不存在则自动在远程机器创建。
解决方案
问题核心原因:TCP/IP连接远程Firebird时,OpenMode := omOpenOrCreate无法触发服务器端创建数据库——客户端传入的本地路径对远程服务器无意义,FireDAC该参数仅在本地连接时生效,远程场景下会因本地存在同名文件误连本地库。
需通过显式调用Firebird服务API创建远程库,具体步骤如下:
步骤1:添加单元引用
在DataModule的单元中添加FireDAC.Phys.FB和FireDAC.Stan.Intf引用,确保能调用Firebird服务接口。
步骤2:修改Connect方法,增加远程创建逻辑
procedure TFD3Base.Connect(const AHost, AFDB: String); var oDef: IFDStanConnectionDef; oParams: TFDPhysFBConnectionDefParams; FBService: TFDPhysFBService; CreateParams: TFDPhysFBCreateDatabaseParams; ConnSuccess: Boolean; begin //clear our datamodule's internal vars FLastError := ''; FDBHost := AHost; FDBName := AFDB; FConDefName := 'BWPMgr_1'; //if we're already connected, drop it if dbConn.Connected then begin dbConn.Connected := False; try FDManager.CloseConnectionDef(FConDefName); except end; end; //does our definition exist? oDef := FDManager.ConnectionDefs.FindConnectionDef(FConDefName); if not Assigned(oDef) then begin //no; create it oDef := FDManager.ConnectionDefs.AddConnectionDef; oDef.Name := FConDefName; //build params oParams := TFDPhysFBConnectionDefParams(oDef.Params); with oParams do begin DriverID := 'FB'; Protocol := ipTCPIP; Server := FDBHost; Database := FDBName; UserName := 'sysdba'; Password := 'masterkey'; // 远程连接时先尝试正常连接,不使用omOpenOrCreate OpenMode := omOpen; end; //apply the changes oDef.MarkPersistent; oDef.Apply; end; // 尝试连接远程数据库 ConnSuccess := False; try dbConn.ConnectionDefName := FConDefName; dbConn.Params.Pooled := FPooled; dbConn.Connected := True; ConnSuccess := True; except on E: Exception do begin FLastError := E.Message; // 判断是否为数据库不存在的错误(匹配Firebird错误码335544344或关键词) if (Pos('335544344', E.Message) > 0) or (Pos('isc_err_db_not_found', E.Message) > 0) then begin // 创建远程数据库 FBService := TFDPhysFBService.Create(nil); try FBService.Params.DriverID := 'FB'; FBService.Params.Protocol := ipTCPIP; FBService.Params.Server := FDBHost; FBService.Params.UserName := 'sysdba'; FBService.Params.Password := 'masterkey'; // 连接到Firebird服务 FBService.Connected := True; // 设置创建数据库的参数 CreateParams := TFDPhysFBCreateDatabaseParams.Create; try CreateParams.Database := FDBName; // 可根据需求设置页面大小、字符集等参数 CreateParams.PageSize := 8192; CreateParams.Charset := 'UTF8'; // 执行创建操作 FBService.CreateDatabase(CreateParams); finally CreateParams.Free; end; // 创建成功后再次尝试连接 dbConn.Connected := True; ConnSuccess := True; finally FBService.Free; end; end else raise; // 其他错误直接抛出 end; end; //if we get here, we're connected; create tables as needed if ConnSuccess then CreateTables; {...} end;
额外注意事项
- 远程路径权限:确保Firebird服务器进程对指定的远程路径有读写权限,否则创建数据库会失败。
- 端口与防火墙:确保远程机器的Firebird默认端口(3050)在VPN网络中开放,防火墙允许访问。
- 错误匹配:不同Firebird版本错误提示可能略有差异,建议同时匹配错误码和关键词,避免遗漏。
内容的提问来源于stack exchange,提问作者Steve Sneed
相关产品推荐
相关产品推荐

