You are not logged in.
Let me explain better the question
Here is a TOrm derived definition:
type
Dmyclass=record myid:TID; othervar:PtrInt; end;
TOrmMyclass=Class(TOrm)
private
function GetfID: TID;
procedure SetfID(const Value: TID);
public
myclassdata:Dmyclass;
class function createxml(_pat: TOrmapipatient; author:ixmldocument; const visdata:Dapidocvisit):rawutf8;
class procedure InitializeTable(const Server: IRestOrmServer; const FieldName: RawUtf8; Options: TOrmInitializeTableOptions); override;
property IDValue: TID read GetfID write SetfID;
property ID: TID read GetID write SetfID;
published
property othervar: PtrInt read myclassdata.othervar write myclassdata.othervar;
end;
function TOrmMyclass.GetfID: TID;
begin
result:=myclassdata.myid;
end;
procedure TOrmMyclass.SetfID(const Value: TID);
begin
fID:=Value;
myclassdata.myid:=value;
end;
I am using this record to be able to copy data from one TOrmMyclass instance to an other by just copying the myclassdata record variable between them.
The problem is that if am using TOrmMyclass.FillFrom to fill TOrmMyclass's instance data from JSON, the ID is filled correctly but not the myclassdata.myid
Can this be possible? Should I change something in the Rtti for that, and how?
Thank you in advance
Offline
I am using this record to be able to copy data from one TOrmMyclass instance to an other by just copying the myclassdata record variable between them.
Why do you want to do it this way? Does not the following also meet your requirements:
type
TOrmItem = class(TOrm)
private
FField1: Integer;
FField2: Integer;
FField3: Integer;
published
property Field1: Integer
read FField1 write FField1;
property Field2: Integer
read FField2 write FField2;
property Field3: Integer
read FField3 write FField3;
end;
var
item1, item2: TOrmItem;
begin
item1 := TOrmItem.CreateWithID(High(Int64));
try
item1.Field1 := 1;
item1.Field2 := 2;
item1.Field3 := 3;
var json: RawJson := item1.GetJsonValues({Expand=} False, {WithID=} True, 'Field1,Field3');
item2 := TOrmItem.CreateWithID(1);
try
ShowMessage(item2.GetJsonValues(True, True, ALL_FIELDS));
item2.FillFrom(Pointer(json));
ShowMessage(item2.GetJsonValues(True, True, ALL_FIELDS));
finally
item2.Free;
end;
finally
item1.Free;
end;
The result is:
{"RowID":1,"Field1":0,"Field2":0,"Field3":0}
{"RowID":9223372036854775807,"Field1":1,"Field2":0,"Field3":3}
With best regards
Thomas
Offline
Why do you want to do it this way? Does not the following also meet your requirements:
I am already using this way, too. But copying a record is much more fast and you can pass it also as a pointer if needed (in a Torm with multiple records)
Offline
AFAIK only published variables will be serialezed, your record is public variable.
Do note that you can use TDocVariantData instead of record, it's much more powerful and sometimes equally fast since it's stored as Variant and that can also be copied by reference.
Last edited by igors233 (2023-10-29 06:57:34)
Offline
AFAIK only published variables will be serialezed, your record is public variable.
Do note that you can use TDocVariantData instead of record, it's much more powerful and sometimes equally fast since it's stored as Variant and that can also be copied by reference.
My record's selected members can be also published properties and being serialized from TOrm (as happens with "othervar" in the above example). TDocVariantData has the same problem with the TOrmMyclass's ID, so the question is the same for it too.
Offline
I'm not sure then where serialization fails, is it when you have a property that writes to a record member or when you have a property that is a record?
Seems you want to have a published properties that are members of record in order to easier exchange those records, that's deinitely non standard behaviour, so it may work or not.
I would suggest to simplify design, define your orm object with fields it needs and have, use simple types for fields, (string, integer) and Variant (json object) where more complex data is required or when you need to exchange data among few classes.
Offline
I'm not sure then where serialization fails, is it when you have a property that writes to a record member or when you have a property that is a record?
Seems you want to have a published properties that are members of record in order to easier exchange those records, that's deinitely non standard behaviour, so it may work or not.
I would suggest to simplify design, define your orm object with fields it needs and have, use simple types for fields, (string, integer) and Variant (json object) where more complex data is required or when you need to exchange data among few classes.
Published properties even when their content is read/written to record members, works like a charm
My problem and my question is about TOrmMyclass's ID that it is double saved to fID and myclassdata.myid
During unserialization with FillFrom and other routines, the SetfID is not used.
I am wondering if a Rtti custom method is used for setting fID and how to change it to use my SetfID procedure
Offline
@dcount
You are defining your own ID property.
The problem is that it is a very special property for TOrm, which is handled specifically by the ORM core.
For compatibility reasons with mORMot 1, it is not even published, and it has the IDValue for direct access and
Using TOrm.fID is hardcoded into the framework core, and can't be overridden.
So the answer to your question is "no, it is not possible to map a TOrm.ID to a record".
Anyway, changing as such the behavior of a parent class in a child class is not a safe approach.
It breaks the SOLID principle, especially the Liskov substitution principle.
Why not go the other way round, and define your record - and not ID: TID as a property with a getter/setter functions?
It is always possible to map a record variable from any other fields, including IDs.
That is what I would have done, if I understand correctly your needs.
Offline
Thank you ab , I have seen the special handle from the source and that is the reason for my question.
The last paragraph, is something I do not know in pascal: How can I map a record variable like myclassdata.myid to fID in Tormmyclass?
Thank you again
Offline
If I understand correctly, your use case is:
I am using this record to be able to copy data from one TOrmMyclass instance to an other by just copying the myclassdata record variable between them.
Just define some methods using this record as parameter, to pass the value.
Something like:
procedure TOrmMyclass.FromData(const myclassdata: Dmyclass);
begin
fID := myclassdata.myid;
fOtherVar := myclassdata.othervar;
end;
procedure TOrmMyclass.ToData(out myclassdata: Dmyclass);
begin
myclassdata.myid := fID;
myclassdata.othervar := fOtherVar;
end;
Offline