#1 2013-11-12 16:51:29

wai-kit
Member
From: Amsterdam, the Netherlands
Registered: 2012-11-27
Posts: 90

How to implement a TSQLRecord descendant w a property of TObjectList ?

Hi,

I am trying to find out what I need to do to implement a class with a property of TOBjectList.

My classes looks like

TSQLPlayer = class(TSQLRecord)
...
end;

TListPlayer = TObjectList<TSQLPlayer>;

TSQLGame = class(TSQLRecord)
private
   fPlayers:TListPlayer;
...
published
   property Players:TListPlayer read fPlayers write fPlayers;
end;

This codes compiles with no errors; But in runtime I get the following exception:
EORMException with message 'Unhanled type for property Players'.

This happens in TSQLModel.Create([TSQLGame, TSQLPlayer], 'root');

Did I failed to do some initialization here?

Merci,

Wai


fpcdeluxe, FPC 3.2 / Lazarus 2.0, mORMot on Windows 10 ...

Offline

#2 2013-11-12 18:55:14

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: How to implement a TSQLRecord descendant w a property of TObjectList ?

Please take a look at the SAD pdf (ensure you get the latest 1.18 revision), about one-to-many relationship in mORMot.
TObjectList is not handled as such.

In short, you have several options, and the better is IMHO data sharding, i.e. using a dynamic array and not a TObjectList.

Online

#3 2013-11-13 08:40:16

wai-kit
Member
From: Amsterdam, the Netherlands
Registered: 2012-11-27
Posts: 90

Re: How to implement a TSQLRecord descendant w a property of TObjectList ?

I think I've read everything about it in the SAD, but probably missed something while searching for TObjectList in the doc. This topic is somewhat
related to http://synopse.info/forum/viewtopic.php?id=1372?


Off topic, but here is something for you :-) http://www.thestupidstation.com/home/im … nd-Marmots.


fpcdeluxe, FPC 3.2 / Lazarus 2.0, mORMot on Windows 10 ...

Offline

#4 2013-11-13 16:21:55

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: How to implement a TSQLRecord descendant w a property of TObjectList ?

Some of those pictures are already in our web site.
smile

Online

#5 2013-12-10 13:18:36

wai-kit
Member
From: Amsterdam, the Netherlands
Registered: 2012-11-27
Posts: 90

Re: How to implement a TSQLRecord descendant w a property of TObjectList ?

Hi Arnaud,

This one sounds stupid (hope I am not wrong), but is there an example of an implementation
of data sharding (in terms of CRUD operations)?
I have changed my TObjectList to a dynamic array. TListPlayer = TObjectList<TSQLPlayer>; is now changed to TListPlayer = array of TSQLPlayer;

I assume this is the correct way, but my ORM update fails .i.e. calling fMormot.Update   (where fMormot is a TSQLRestServer).

My code looks like

    TSQLGame = class(TSQLRecord)
     ...
     published
         fPlayers:TListPlayer;
     end;


    aGame := TSQLGame.CreateAndFillPrepare(fMormot, 'GameIdentifier=?', [aGameIdentifier]);
    try
      if not assigned(aGame) then
        aStatus := cstStatusGameNotFound
      else begin
        aPlayer := TSQLPlayer.CreateAndFillPrepare(fMormot, 'ID=?', [aPlayerID]);
        if not assigned(aPlayer) then
          aStatus := cstStatusPlayerNotFound
        else begin
          aStatus := aGame.AddPlayer(aPlayer);       <<<--- adds a TSQLPlayer object to the array fPlayers
          if aStatus <> cstStatusGameIsFull then begin
            if fMormot.Update(aGame) then begin      <<<--- this returns false!

Hope this picture is clear.


fpcdeluxe, FPC 3.2 / Lazarus 2.0, mORMot on Windows 10 ...

Offline

#6 2013-12-10 14:19:23

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: How to implement a TSQLRecord descendant w a property of TObjectList ?

Your dynamic array should be a dynamic array of records, not a dynamic array of class instances.
So it won't work as you expect here.

You need either:
- use a dynamic array of integers, containing the TSQLPlayer IDs
- use a many-to-many relationship (see the SAD pdf)
- change the TSQLPlayer from a TSQLRecord into a record, then use a dynamic array of records

Online

#7 2014-07-29 23:47:34

AntonE
Member
Registered: 2012-02-03
Posts: 74

Re: How to implement a TSQLRecord descendant w a property of TObjectList ?

Hello.
Is this still the case? On page 112 of SAD 1.18 it says "The following published properties types are handled by the ORM..." and lists TObjectList.
Or am I misunderstanding it?

Offline

#8 2014-07-30 09:52:37

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: How to implement a TSQLRecord descendant w a property of TObjectList ?

TObjectList does not define the class type to be serialized.
So it may be difficult to unserialize it afterwards.
It should work in some cases, but you need to register the classes before.

What works straightly is to use a TCollection, or a dynamic array of records.

Online

#9 2014-07-30 11:50:09

AntonE
Member
Registered: 2012-02-03
Posts: 74

Re: How to implement a TSQLRecord descendant w a property of TObjectList ?

I would really like to use TObjectList as it makes LiveBindings easier for nested (sharded?) objects.
I have my objects defined as this and register the ITem class:

uses mORMot,SynCommons,Contnrs;


type TItem       = class(TObject)
                    private
                     fItemName: RawUTF8;
                     fItemCode: Integer;
                    published
                     property ItemName   : RawUTF8 read fItemName write fItemName;
                     property ItemCode   : Integer read fItemCode write fItemCode;
                   end;
type TSQLNested  = class(TSQLRecord)
                    private
                     fName: RawUTF8;
                     fItems: TObjectList;
                    public
                     constructor Create;
                    protected
                     destructor Destroy;override;
                    published
                     property Name  : RawUTF8     read fName  write fName;
                     property Items : TObjectList read fItems write fItems;
                   end;

function CreateDataModel: TSQLModel;

implementation

function CreateDataModel: TSQLModel;
begin
 result := TSQLModel.Create([TSQLNested]);
 TJSONSerializer.RegisterClassForJSON(TItem);
end;

But I still get error:
Unhandled stfUnknown/tkClass type for property Items.
Seems unrelated to TItem and it does not like the TObjectList. Also tried with Generics.Collections version.

Last edited by AntonE (2014-07-30 11:53:03)

Offline

#10 2014-07-30 17:34:38

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: How to implement a TSQLRecord descendant w a property of TObjectList ?

Sounds like if there was indeed a problem.

Now TObjectList published properties will be recognized as sftObject kind.
See http://synopse.info/fossil/info/b5724a6c644d8

Online

#11 2014-07-31 10:04:57

AntonE
Member
Registered: 2012-02-03
Posts: 74

Re: How to implement a TSQLRecord descendant w a property of TObjectList ?

Thank you very much, it's working one level deep. smile
Test project here:
ftp://ftp.true.co.za/TestORM.zip

If compiled as-is it works, compile with conditional directive TWOLEVELS to make another TObjectList within a TObject class and it fails to persist even first level.
JSONvalues looks right when updating but I'm a bit lost 'deeper inside' mORMot yet.

This can be very powerful.

Offline

#12 2014-07-31 20:16:32

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: How to implement a TSQLRecord descendant w a property of TObjectList ?

Your classes should inherit from TPersistent and not TObject, to have the needed RTTI for published properties, AFAIK.

Online

#13 2014-07-31 23:34:49

AntonE
Member
Registered: 2012-02-03
Posts: 74

Re: How to implement a TSQLRecord descendant w a property of TObjectList ?

I figured my problem out. roll
Subitem that have properties that need init code, like TObjectList only have e.g. TObject.Create called and it's not virtual.
If I descend from TSQLRecord instead of TObject (even not register it to Model), then I can make

Constructor Create;override;

and it therefore works perfectly multiple-levels deep.

Regards

Last edited by AntonE (2014-07-31 23:36:21)

Offline

#14 2014-08-01 07:33:05

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: How to implement a TSQLRecord descendant w a property of TObjectList ?

Or you can just use TPersistentWithCustomCreate instead of TSQLRecord.

It may be less confusing, since your nested class are not part of the ORM (nor defined in the data model), but just value objects.

Online

Board footer

Powered by FluxBB