I offloaded all ADO hood in a separate Data Module, so a single module can be referred by several applications. All my applications basically need only two worker methonds to access data:
AdoQuery
delivers a result set in a form of TADODataSet
.
AdoExecute
performs simple update/delete queries without fetching any results.
Here is the class structure:
type
TMyDataModule = class(TDataModule)
procedure DataModuleCreate(Sender: TObject);
procedure DataModuleDestroy(Sender: TObject);
private
procedure pvtAdoConnect;
procedure pvtAdoExecute(const sql: string);
function pvtAdoQuery(const sql: string): TADODataSet;
public
AdoConnection: TADOConnection;
end;
Then I added two publicly exposed wrappers to class methods. I used that to avoid long class references in the calls:
function AdoQuery(const sql: string): TADODataSet;
procedure AdoExecute(const sql: string);
implementation
function AdoQuery(const sql: string): TADODataSet;
begin
Result := MyDataModule.pvtAdoQuery(sql);
end;
Above are the worker function which I call from within all my forms.
AdoConnect
runs only once on DataModuleCreate
event. TDatModule derived from TPersistent
, which allows to persist the single instance of connection throughout a runtime.
The only thing that annoys me so far - is a useless .DFM which I don't need at all.
Is there any option to get rid of it?
I would handle this type of thing in one of two ways, with interfaces or with inheritance. I prefer not to expose classes to the outside world in these cases. The second one could almost be called an interface without interfaces :)
Interfaces
This version returns an interface that includes the required methods. The outside world only needs to use the interface. We keep the implementation details private. Our TMyDBClass implements the interface that we have exposed to the outside world and our global function
GetDBInterface
returns the single instance.Inheritance
This version uses a base class that has the required methods. This is a bit easier for people to deal with because it excludes the interface which can be complex to people starting out. Again we hide the implementation details from the user and only expose a shell of a class that includes the two methods we want people to access. The implementation of these methods is performed by a class in the implementation that inherits from the exposed class. We also have a global function that returns the instance of this class. The big advantage that the interface approach has over this approach is that the user of this object can't free the object by accident.
Usage
Usage of these are really easy.