Designing an Object in hcOPF

hcOPF uses TField like attributes to represent the attributes of an object.  These ThcAttribute descendants provide an object with the ability to Undo any changes made to it’s attributes and notify other Delphi objects when changes have been made.  They are the foundation of the framework, providing a generic, re-usable way of representing object attributes without using simple types and Reflection with it’s limitations and overhead.  In order to specify the attributes for an object and how they’re stored and used, the developer needs to provide the framework with information in some form.  This is Metadata, and although it could be represented in various ways, including XML, in hcOPF it’s currently code.

MetaData is used by the framework to construct an object with the appropriate attributes, based on how the object is stored in an RDBMS.  Every ThcObject descendant must override the Register class method and register it’s metadata with the framework.  A typical Register method would be as follows:

class procedure TPerson.Register;
var
  MetaData: ThcMetaData;
  aDef :ThcAttributeDef;
begin
  MetaData := ThcMetaData.Create;
  with MetaData do
  begin
    with TableDefs.AddTableDef('Person','P',[tpUpdateable,tpInsertable]) do
    begin
      with AttributeDefs do
      begin
        aDef := AddDef('Person_ID',ftInteger,'ID',ftInteger,
                       [apPrimaryKey,apServerGeneratedBeforeInsert]);
        OID := ThcOID.Create('Person',[aDef]);
        AddDef('FirstName',ftString,'FirstName',ftString,[apRequired],30);
        AddDef('LastName',ftString,'LastName',ftString,[apRequired],30);
      end; //with
    end;  //with
  end;  // with
  ObjectRegistry.RegisterObject(TPerson,MetaData);
end;

The lifetime of the MetaData is managed for you, but since the Register procedure is not a callback, you must create the MetaData object.  Metadata contains the definition of the tables where the object attributes are stored and their relationships.  So you begin by adding a Table Definition to the Metadata, specifying the RDBMS table and whether the framework is allowed to insert or update rows in that table.  Then you add Attribute Definitions which essentially specify the column and it’s type in the RDBMS and the corresponding attribute name and type in the OPF.  The OPF is capable of translating database types into internal Delphi types and OPF attributes to some degree.  More on that later…

The final line in every Register() routine should be a call to register the object with the framework.  Namely:

ObjectRegistry.RegisterObject(TPerson,MetaData);

Then somewhere in the project you need to call the Register class method for all objects.  I typically do this in the initialization section of the same unit in which the business object is defined.  In the finalization section you should also call the UnRegister method, although technically this is not necessary since the application termination will reclaim the memory.

initialization
  TPerson.Register;
finalization
  TPerson.UnRegister;

In hcOPF a ThcAbstractFactory descendant is the object that is responsible for persisting a ThcObject descendant. To get a factory instance you request it from a FactoryPool.  All applications must contain 3 core objects:  a FactoryPool, a SQLMapper, and a TransactMgr.  Normally you would drop these components onto your main datamodule and hook them up like this:

The FactoryPool knows about the different factory classes available for persistence.  In this case, IBX has been chosen as the DAL for a FireBird database.  Once the datamodule has been created and the database is connected, you can load and persist objects as you wish.

For a simple example on using the framework with standard Delphi controls see the following.  This application has a rather contrived database structure used to show lazy loading (even though it’s triggered immediately) with a child object.  This example also shows how to display content from two different objects on the same form, and persist them in a single transaction.  The database included was created with Firebird 2.0.  I have included a script as well so you can use Interbase if you prefer.  I also included the EXE in case you want to run the application without setting up the framework to compile the project.

Tags: ,

2 Responses to “Designing an Object in hcOPF”

  1. Firebird News » Designing an Object in hcOPF Says:

    [...] hcOPF (persistence framework for delphi) example with Firebird 2.0 Permalink Leave your comment [...]

  2. João Vieira Says:

    Hi,

    Your framework is great. Congratulations.

    How can I contribute with some code?

    Best regards.

    João

Leave a Reply