Extending TObjectManager for "logical" removal

Hi, Im trying to migrate and rewrite a lot of our program functionality using Aurelius. Although I´ve searched the documentation and looked I couldn´t find a solution for my problem which is: When a user "removes" a record from the database I want it to be erased logically, instead of being erased or removed totally from the database (as Aurelius currently does), using SQL I want to do the following:


Change to this:

UPDATE object_table SET erased_at = TODAY() WHERE id = 1

instead of:

DELETE FROM object_table WHERE id = 1 

 (as Aurelius does it right now)


I´ve tried the following approach:

1. Create a Interface that all of my "not really erasable" objects will support:


type

   IDeletable = Interface(IInterface)
     ['{60F37191-5B95-45BC-8C14-76633826889E}']
     function IsDeleted() : Boolean;
     property Deleted: Boolean read IsDeleted;
     procedure Delete;
   end;




And in the classes that uses Aurelius:



    [Entity]
    [Automapping]
    TCustomer = class(TInterfacedObject, IDeletable)
    private
       function IsDeleted() : Boolean;
       sName: String;
       fDeletedAt: TDateTime;
    published
        property Deleted: Boolean read IsDeleted;
        poperty Name : String read sName write sName;
        procedure Delete;
    end;


Finally, I created my "own" TObjectManager the following way:



type


  TMyObjectManager = class(TObjectManager)
  public
      procedure Remove(Entity: TObject);
  end;


implementation


uses SysUtils;


procedure TMyObjectManager.Remove(Entity: TObject);
var
   Object : IDeletable;
begin
   if Supports(Entity, IDeletable, Object) then
   begin
     // The following method only establishes a "deleted_at" date time field. 
     Object.Delete;
     Self.Flush;
   end else
      inherited Remove(Entity);
end;




And for the use I use it as I would use Aurelius TObjectManager:




var
    Manager : TMyObjectManager;
begin
/// Manager creation and initialization...
Customer := Manager.Find<TCustomer>(1);
Manager.Remove(Customer);
end;




Now, for the final part, everything compiles and "seems to work", however when I try to Remove an object using my own TObjectManager, it raises an exception with the following message:

Cannot find attribute [id] on class TPersistent.

Any ideas? 

Thanks in advance

Well, after several attempts, I´ve seem to have solved it. In case somebody is interested I implemented it as follows:



	procedure TMyObjectManager.Remove(Entity: TObject);
var
   Object : IDeletable;
begin
   if SysUtils.Supports(Entity, GetTypeData(TypeInfo(IDeletable))^.Guid, Object) then
   begin
     // The following method only establishes a "deleted_at" date time field. 
     Object.Delete;
     Self.Flush;
   end else
      inherited Remove(Entity);
end;


Now, in order to "avoid" the auto releasing of objects using interfaces I implemented my own TInterfacedObject implementation which is:




type



TMyInterfacedObject = class
    protected
        function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
        function _AddRef: Integer; stdcall;
        function _Release: Integer; stdcall;
    end;


implementation


function TMyInterfacedObject.QueryInterface(const IID: TGUID; out Obj): HResult;
const
  E_NOINTERFACE = HResult($80004002);
begin
  if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE;
end;




function TMyInterfacedObject._AddRef: Integer;
begin
  Result := -1   // -1 indicates no reference counting is taking place
end;


function TMyInterfacedObject._Release: Integer;
begin
  Result := -1   // -1 indicates no reference counting is taking place
end;




Which uses the principle described in: http://stackoverflow.com/questions/4044712/introducing-interfaces-into-an-existing-class-hierarchy-in-delphi

Now the definition of the class which uses Aurelius is:



[Entity]
    [Automapping]
    TCustomer = class(TMyInterfacedObject, IDeletable)
    private
       function IsDeleted() : Boolean;
       sName: String;
       fDeletedAt: TDateTime;
    published
        property Deleted: Boolean read IsDeleted;
        poperty Name : String read sName write sName;
        procedure Delete;
    end;


Now everything works as expected. Hope it helps somebody :)