使用FireDAC的TFDManager和TFDConnection組件實現(xiàn)運行時動態(tài)數(shù)據(jù)庫連接
以下是一個通用的數(shù)據(jù)庫連接方案,使用FireDAC的TFDManager和TFDConnection組件實現(xiàn)運行時動態(tài)數(shù)據(jù)庫連接。支持多種數(shù)據(jù)庫類型,采用面向?qū)ο蠓庋b:
unit DatabaseManager;
interface
uses
System.SysUtils, System.Classes, FireDAC.Stan.Intf, FireDAC.Stan.Option,
FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,
FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Comp.Client,
FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt, Data.DB,
FireDAC.Comp.DataSet;
type
TDatabaseType = (dtSQLite, dtMySQL, dtPostgreSQL, dtMSSQL, dtOracle);
TDatabaseManager = class
private
FConnection: TFDConnection;
FManager: TFDManager;
FDatabaseType: TDatabaseType;
FLastError: string;
procedure ValidateDriver;
function GetConnectionDefName: string;
function GetDriverName: string;
function BuildParams(Params: TStrings): string;
public
constructor Create;
destructor Destroy; override;
procedure ConfigureConnection(DatabaseType: TDatabaseType; Params: TStrings);
function Connect: Boolean;
procedure Disconnect;
function ExecSQL(const SQL: string; Params: TArray<TVarRec>): Integer;
function OpenQuery(const SQL: string; Params: TArray<TVarRec>): TFDQuery;
property LastError: string read FLastError;
end;
implementation
{ TDatabaseManager }
constructor TDatabaseManager.Create;
begin
FManager := TFDManager.Create(nil);
FConnection := TFDConnection.Create(nil);
FManager.SilentMode := True;
FManager.Active := True;
end;
destructor TDatabaseManager.Destroy;
begin
Disconnect;
FConnection.Free;
FManager.Free;
inherited;
end;
procedure TDatabaseManager.ConfigureConnection(DatabaseType: TDatabaseType; Params: TStrings);
begin
FDatabaseType := DatabaseType;
FManager.ConnectionDefs.Clear;
// 添加新的連接定義
FManager.AddConnectionDef(
GetConnectionDefName,
GetDriverName,
BuildParams(Params)
);
end;
function TDatabaseManager.Connect: Boolean;
begin
Result := False;
try
ValidateDriver;
FConnection.ConnectionDefName := GetConnectionDefName;
FConnection.Connected := True;
Result := True;
FLastError := '';
except
on E: Exception do
FLastError := '連接失敗: ' + E.Message;
end;
end;
procedure TDatabaseManager.Disconnect;
begin
if FConnection.Connected then
FConnection.Connected := False;
end;
function TDatabaseManager.ExecSQL(const SQL: string; Params: TArray<TVarRec>): Integer;
var
Query: TFDQuery;
begin
Result := -1;
Query := TFDQuery.Create(nil);
try
Query.Connection := FConnection;
Query.SQL.Text := SQL;
if Length(Params) > 0 then
Query.MacroByName('params').Value := Params;
Query.ExecSQL;
Result := Query.RowsAffected;
finally
Query.Free;
end;
end;
function TDatabaseManager.OpenQuery(const SQL: string; Params: TArray<TVarRec>): TFDQuery;
begin
Result := TFDQuery.Create(nil);
try
Result.Connection := FConnection;
Result.SQL.Text := SQL;
if Length(Params) > 0 then
Result.MacroByName('params').Value := Params;
Result.Open;
except
Result.Free;
raise;
end;
end;
// 私有方法實現(xiàn)
procedure TDatabaseManager.ValidateDriver;
begin
case FDatabaseType of
dtSQLite: FDPhysSQLiteDriverLink.Create(nil);
dtMySQL: FDPhysMySQLDriverLink.Create(nil);
dtPostgreSQL: FDPhysPgDriverLink.Create(nil);
dtMSSQL: FDPhysMSSQLDriverLink.Create(nil);
dtOracle: FDPhysOracleDriverLink.Create(nil);
end;
end;
function TDatabaseManager.GetConnectionDefName: string;
begin
Result := Format('%s_Connection', [GetEnumName(TypeInfo(TDatabaseType), Ord(FDatabaseType))]);
end;
function TDatabaseManager.GetDriverName: string;
begin
case FDatabaseType of
dtSQLite: Result := 'SQLite';
dtMySQL: Result := 'MySQL';
dtPostgreSQL: Result := 'PG';
dtMSSQL: Result := 'MSSQL';
dtOracle: Result := 'Ora';
else
raise Exception.Create('不支持的數(shù)據(jù)庫類型');
end;
end;
function TDatabaseManager.BuildParams(Params: TStrings): string;
var
I: Integer;
begin
Result := '';
for I := 0 to Params.Count - 1 do
Result := Result + Format('%s=%s;', [Params.Names[I], Params.ValueFromIndex[I]]);
end;
end.
使用示例:
// 創(chuàng)建數(shù)據(jù)庫管理器
var
DB: TDatabaseManager;
Params: TStringList;
Query: TFDQuery;
begin
DB := TDatabaseManager.Create;
try
// 配置SQLite連接
Params := TStringList.Create;
try
Params.Values['Database'] := 'C:\Data\mydb.sqlite';
Params.Values['OpenMode'] := 'CreateUTF8';
DB.ConfigureConnection(dtSQLite, Params);
finally
Params.Free;
end;
if DB.Connect then
begin
// 執(zhí)行SQL命令
DB.ExecSQL('CREATE TABLE IF NOT EXISTS Users (ID INTEGER PRIMARY KEY, Name TEXT)');
// 執(zhí)行查詢
Query := DB.OpenQuery('SELECT * FROM Users');
try
while not Query.Eof do
begin
ShowMessage(Query.FieldByName('Name').AsString);
Query.Next;
end;
finally
Query.Free;
end;
end
else
ShowMessage(DB.LastError);
finally
DB.Free;
end;
end;
功能特點:
- 多數(shù)據(jù)庫支持:
- 支持SQLite、MySQL、PostgreSQL、SQL Server和Oracle
- 通過
TDatabaseType枚舉輕松擴展新數(shù)據(jù)庫類型
- 動態(tài)配置:
- 安全連接管理:
- 自動驗證數(shù)據(jù)庫驅(qū)動
- 內(nèi)置錯誤處理機制
- 連接資源自動釋放
- 靈活的參數(shù)化查詢:
- 事務支持(可擴展):
配置參數(shù)說明:
|
數(shù)據(jù)庫類型 |
必需參數(shù) |
示例值 |
|
SQLite |
Database, OpenMode |
Database=C:\data\test.sdb |
|
MySQL |
Server, Database, User_Name, Password |
Server=192.168.1.100;Port=3306 |
|
PostgreSQL |
Server, Database, User_Name, Password |
Port=5432 |
|
MSSQL |
Server, Database, User_Name, Password |
OSAuthent=Yes |
|
Oracle |
Server, User_Name, Password |
ServiceName=ORCL |
最佳實踐建議:
- 連接池配置:
- 性能優(yōu)化:
- 安全增強:
- 日志記錄:
- 多線程支持:
該方案通過面向?qū)ο笤O計實現(xiàn)了以下優(yōu)勢:
1. 高內(nèi)聚低耦合:數(shù)據(jù)庫操作邏輯與業(yè)務邏輯分離
2. 可擴展性:新增數(shù)據(jù)庫類型只需擴展枚舉和驅(qū)動驗證
3. 類型安全:強類型參數(shù)減少運行時錯誤
4. 資源管理:自動釋放連接和查詢對象
5. 統(tǒng)一接口:所有數(shù)據(jù)庫操作使用相同的方法簽名
可根據(jù)具體需求擴展以下功能:
- 連接狀態(tài)監(jiān)控
- 執(zhí)行計劃分析
- 批量數(shù)據(jù)操作
- 數(shù)據(jù)庫元數(shù)據(jù)查詢
- 異步操作支持
- 連接故障轉(zhuǎn)移機制

浙公網(wǎng)安備 33010602011771號