type
{ hier mal die Schnittstellen, wie ich sie mir grob vorstelle... }
{ keine korrekte Implementierung; in logischer Reihenfolge präsentiert }
IDbConnectionInformation =
interface
function ToString():
string;
end;
IDbConnection =
interface
procedure SetConnectionInformation(AConnectionInformation: IDbConnectionInformation);
procedure Open();
procedure Close();
function GetQuery(): IDbQuery;
end;
IDbConnectionManager =
interface
procedure SetConnectionInformation(AConnectionInformation: IDbConnectionInformation; ADatabaseID:
string = '
default');
function GetConnection(ADatabaseID:
string = '
default'): IDbConnection;
end;
IDbQuery = interace
procedure SetSQL(ASQL:
string);
// procedure SetParam() -> muss ich noch schauen, wie das mache
procedure Execute();
function Open(): IDbDatasetEnumerator;
// zum einfachen durchgehen der Datensätze
procedure Close();
end;
IDbDataset =
interface
// für die Beschreibung eher irrelevant
end;
IDbDatasetEnumerator =
interface
// für die Beschreibung eher irrelevant
end;
// Nun eine Basisimplementierung, die die Idee von oben repräsentiert. Der Rest
// der Interfaces ist für die Idee eher uninteressant, daher überlasse ich es
// dem Leser das mal auszuprogrammieren ;)
TBaseDbManager =
class(TInterfacedObject, IDbConnectionManager)
private
FConnectionInformation : TDictionary<
string, IDbConnectionInformation>;
FConnections : TDictionary<TThreadID, IDbConnection>;
public
function GetConnection(ADatabaseID:
string = '
default'): IDbConnection;
end;
function TBaseDbManager.GetConnection(ADatabaseID:
string = '
default'): IDbConnection;
begin
FCriticalSection.Enter();
try
// Wenn noch keine Verbindung für den aktuellen Thread besteht, dann wird eine
// aufgebaut
if (
not FConnections.ContainsKey(GetCurrentThreadID()))
then
FConnections.Add(GetCurrentThreadID(), DbConnectionFactory.Create(FConnectionInformation[ADatabaseID]));
// Anschließend existiert immer eine Verbindung für den aktuellen
// Thread, also kann eine zurückgegeben werden
Result := FConnections[ADatabaseID];
finally
FCriticalSection.Leave();
end;
end;
{ Nun zur Implementierung, aber nur die wichtigsten Stellen... }
// Beim Start wird der DbConnectionManager mit den nötigen Informationen gefüttert, sodass
// dieser alle Daten für den Verbindungsaufbau hat und somit automatisch Verbindungen
// zurückgeben kann.
// Ich habe einen globalen ServiceLocator, der mir auf Anfrage eine Singleton-Instanz
// eines speziellen Typs, der sich vorher registriert hat zurück gibt. Natürlich kann man
// sowas auch anders lösen.
procedure TApplication.Startup();
var
DbConnectionInformation : TDictionary<
string, IDbConnectionInformation>;
DbConnectionManager : IDbConnectionManager;
begin
DbConnectionInformation := LoadAndBuildDbConnectionInformation();
// z.B.
// DbConnectionInformation['default'] = Verbindung zu Oracle
// DbConnectionInformation['access'] = Verbindung zu Access
// DbConnectionInformation['access-lan'] = Verbindung zu Access-DB, die im LAN liegt
// Fülle den DbManager mit den Verbindungsinformationen
DbConnectionManager := ServiceLocator.GetService('
database');
for ConnectionInformation
in DbConnectionInformation
do
DbConnectionManager.AddConnectionInformation(ConnectionInformation);
end;
{ und hier nun die Nutzung... für jeden Thread wird hier automatisch }
{ eine Verbindung aufgebaut und darüber gearbeitet. }
var
DbConnectionManager : IDbConnectionManager;
DbConnection : IDbConnection;
Query : IDbQuery;
Dataset : IDbDataset;
begin
DbConnectionManager := ServiceLocator.GetService('
database')
DbConnection := DbConnectionManager.GetConnection();
Query := DbConnection.GetQuery();
// Natürlich geht auch
Query := ServiceLocator.GetService('
database').GetConnection().GetQuery();
// Oder wenn man auf eine andere DB zugreifen will. Vorher muss man aber die
// entsprechende ConnectionInfo dem DbConnectionManager zugeführt haben.
Query := ServiceLocator.GetService('
database').GetConnection('
sqlite').GetQuery();
Query.SetSQL('
SELECT * FROM BlubTable');
try
for Dataset
in Query.Open()
do
begin
ShowMessage(Dataset.GetField('
Text').ToString());
end;
finally
Query.Close();
end;
end;