Data Modeler - Aurelius with Interfaces

I use the bundle TMS Data Modeler with TMS Aurelius. What I (and many of my customers) need is interfaced data objects. In all projects we never pass TObject (descendants) to operations, only interfaces. We can accomplish this with Aurelius by adding all interfaces manually and modifying the auto-exported classes. Of course, it would be extremely helpful if the generated code already contains interfaces for each object.

Also: In the Aurelius documentation page 26 explains the use of the IDBConnection interface with a SQLite connection. In the code example the object is both referenced as an interface and an object. This should never be mixed! The example introduces a memory-leak at best, or and a AV exception.
Properties (fields) that only exists on the class (and not in the interface) should be set with the constructor, as parameters.


But how to you expect Data Modeler to model such interfaces? What do you need to predefine in Data Modeler to get exported to Aurelius source code?

The mentioned code doesn't have any problem. You can mix objects and interfaces as long you know what your doing. In the example, the object is used to access the properties and later the reference is put in a interface variable, thus the object can be "discarded" and reference counting for the interface is in action. What is dangerous is use the object reference after the interface is in use (so the interface reference count can go to zero and the object becomes invalid). But that's not the case in the code (the code even mentions you should use the interface from that point in code and later)
Hi Wagner,

Thanks for your reply. The Data Modeler does not have to model the interfaces. Only one extra edit box is necessary to ask the user for the name of the unit that will contain the interfaces. It is good practice to separate the interfaces from the classes. All information you need to generate the code that describes the interfaces is right there in the currently implemented export that generates the classes (unit). I am actually thinking of writing a tittle tool that will export the interfaces from the classes unit file by parsing the pascal code.

For example: TMyTable = class(TObject) becomes:
TMyTable = class(TInterfacedObject, IMyTable)

IMyTable should then obviously declare the getters and setter and properties. The TMyObject should only declare and implement the getters and setters. Of course, the TObjectManager should support interfaces. This would give the user the choice to work with objects or interfaces. But preferably not both.

You are right about the code in the manual being correct. However, it is never good practice to mix objects and interfaces. It's high-risk code and in your case completely unnecessary. Only mix when you have no other option and know exactly what you are doing, and you are sure that the next programmer working on the code has the same knowledge you have. On page 21 of the manual the constructor of the adapter should include the EnableForeignKeys parameter. Then it is no longer   necessary to use it as an object. The function can't be turned of at a later moment but that isn't an argument because in the current design the situation is the same because you (should) discard the object reference anyway.

Another way is to use interface inheritance from IBConnection. See the example below. With this method there is no need to use an object reference and the new interface can easily be passed as an IDBConnection.

  ISQLiteConnection = interface(IDBConnection) ['{0082DF45-7F6C-4AFF-9A02-BD9417E018EE}']
    procedure EnableForeignKeys;
    procedure DisableForeignKeys;

  TSQLiteNativeConnectionAdapter = class(TInterfacedObject, IDBConnection, ISQLiteConnection)
    procedure EnableForeignKeys;
    procedure DisableForeignKeys;

  SQLiteAdapter: ISQLiteConnection;
  MySQLiteConnection: IDBConnection;
  SQLiteAdapter := TSQLiteNativeConnectionAdapter.Create();
  MySQLiteConnection := SQLiteAdapter;

I really think that TMS Aurelius is a great product. There are a lot more features to wish for that one can think of but the current base is a stable and elegant implementation of ORM that saves me a lot of time. Thank you for that.


You suggestion about an inherited interface is good, I just thought it was over-engineering, since the example is just the only situation in which it will be used, and the code in the manual is just fine. Also, passing all parameters in constructor is not an option imho because there might be more settings later, I wouldn't be happy with lots of overloaded constructors and/or default parameters.

About the Data Modeler generating the interfaces, it's a good option, indeed, but you said yourself: better not mix objects and interfaces. It would be a LOT complex. In a way, you contradicts yourself :) The mentioned example in manual is very simple, specific and controlled.
But how do you expect TObjectManager to handle BOTH objects and interfaces? I'm interested to hear, because I can't see a good solution so far. Note that Aurelius is already stable and being used by a lot of users, so removing objects support is not an option.