#1 2016-02-26 03:16:07

mik
Member
Registered: 2015-10-14
Posts: 8

TSQLRecord: is there a way to selectively store published properties?

Assume that I have a record defined as:

TBaby = class
  private
    fName: RawUTF8;
    fYear: Integer;
    fSex: RawUTF8;
  published
    property Name: RawUTF8 read fName write fName;
    property Year: Integer read fYear write fYear;
    property Sex: RawUTF8 read fSex write fSex;
end;

TSQLBaby = class(TSQLRecord)
  private
    fBaby: TBaby;
  published
    property Baby: TBaby read fBaby write fBaby;
end;

Normally when TSQLBaby is stored in the database, the field "Baby" will contain JSON text, for example:

{"Name":"Jim","Year":2010,"Sex":"M"}

I'd like to be able to control which of the published fields get stored in the database on TSQLBaby.Add or TSQLBaby.Update

Is there a way to store (depending on some program logic) only subset of the published properties?
I'd like, for example, to omit "sex" for certain records and have some babies stored as:

{"Name":"Ann","Year":2014}

Can you please let me know if this is possible?
Thank you.

Offline

#2 2016-02-26 05:37:26

edwinsn
Member
Registered: 2010-07-02
Posts: 1,215

Re: TSQLRecord: is there a way to selectively store published properties?

AFAIK It's not possible with the current version.

I guess that can be achieved by using attributes (http://wiki.freepascal.org/Property_attributes), which is also supported by FPC (). But I'm afraid Arnaud will have to abandon support for earlier versions of Delphi and Kylix, but I doubt he will.

Another idea would be allow defining a class method for TSQLRecord, something like TSQLRecord.GetAutoPersistedFieldsInCSVFormat(), where people can return a CSV-formatted string like 'ID, Name, Year', to define which fields will be handled by the framework. But I'm not sure if that will work, ab can tell us smile


Delphi XE4 Pro on Windows 7 64bit.
Lazarus trunk built with fpcupdelux on Windows with cross-compile for Linux 64bit.

Offline

#3 2016-02-26 07:51:30

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

Re: TSQLRecord: is there a way to selectively store published properties?

You may simply use the persistence mapping as implemented for DDD Aggregates.

See http://synopse.info/files/html/Synopse% … l#TITL_169

Offline

#4 2016-02-26 17:41:36

mik
Member
Registered: 2015-10-14
Posts: 8

Re: TSQLRecord: is there a way to selectively store published properties?

Thanks for the answers!
Sorry, I might not be knowledgeable in the entire framework, but I'm trying to learn smile
I studied the DDD chapter, but so far I don't see how I can may it work with my specific request.
DDD to ORM mapping (as far as I understand) suggests to "flatten" the structure instead of serializing object to JSON and storing it in a single field, but this is exactly what I want to avoid and I'd like to maintain the aggregate (JSON) storage in a single field.
Besides, I think that mapping between DDD and ORM is static, while in my case I want specifically "dynamic" mapping, i.e. selective subset of stored properties, individual for every record.
If I totally misunderstood the suggestion - can you please give more details or point me to the right direction and perhaps recommend some sample I can study?

Offline

#5 2016-02-26 19:28:07

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

Re: TSQLRecord: is there a way to selectively store published properties?

So take a look at the TDocVariant type in our documentation, and use "variant" fields to store such "dynamic" content.
You may be amazed by the result: a NoSQL schemaless power in a regular SQL database...

Offline

#6 2016-02-26 20:48:14

mik
Member
Registered: 2015-10-14
Posts: 8

Re: TSQLRecord: is there a way to selectively store published properties?

ok, thanks. This part I understand perfectly - and I see how to do this with "variant" field. I was just looking for a simpler way. My object has several dozens of published properties, and saving it via TDocVariant is more pain than using standard ObjectToJSON -> TJSONSerializer.

so I really was looking to find something similar to what edwinsn suggested or some "callback" function in TSQLRecord which would ask me to "approve" or "deny" each stored property of any processed object.

I'd like also briefly explain why this scenario makes sense to me: in my app, when I instantiate the object, it is created with the "default" values for each property. The defaults are controlled by application, and user may customize them. When user recovers the "stored" object, it is essential (in some specific cases) that he only "overrides" a subset (critical) of properties of its instantiated object, i.e. the stored object only maintains and overrides part of the the properties, leaving the rest intact (i.e. according to user-specific defaults). The content of this stored object must be dynamic in my case, i.e. the "saved subset" might be different in different saved objects (records).

Last edited by mik (2016-02-26 20:52:01)

Offline

#7 2016-02-26 21:55:30

mpv
Member
From: Ukraine
Registered: 2012-03-24
Posts: 1,544
Website

Re: TSQLRecord: is there a way to selectively store published properties?

You can define stored function for each published property of your class. And use doNotStoreDefault options during serialisation. I do this in my code. Unfortantly in this case we ned to add many functions in classes.

 
TBaby = class
  private
    fName: RawUTF8;
  function canStoreName: boolean;
  published
    property Name: RawUTF8 read fName write fName stored canStoreName;
end;
 

Offline

#8 2016-02-27 00:49:42

mik
Member
Registered: 2015-10-14
Posts: 8

Re: TSQLRecord: is there a way to selectively store published properties?

thanks, mpv!
This looks like a possible solution. Fortunately, it appears that [woDontStoreDefault] is used by default in TJSONSerializer

Offline

#9 2016-02-27 10:29:22

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

Re: TSQLRecord: is there a way to selectively store published properties?

Why not just use a variant field, with getter and setter methods ?
The read/write methods would use a temporary TDocVariantData for customizing the serialization.
Then it would be stored as a JSON content, and you would be able to tune the serialization at runtime, just as you wish.

Offline

#10 2016-02-27 17:21:55

mik
Member
Registered: 2015-10-14
Posts: 8

Re: TSQLRecord: is there a way to selectively store published properties?

Thanks, ab! I will check out both approaches. My first intuitive impression, is that mpv's suggestion may be preferrable if there are only a few properties (out of many) which have to be optionally stored - the code seems to be cleaner and easier to understand with this approach. The TDocVariant method might work better in my case, where all the numerous properties are stored optionally.

Offline

#11 2018-02-06 12:18:16

mpv
Member
From: Ukraine
Registered: 2012-03-24
Posts: 1,544
Website

Re: TSQLRecord: is there a way to selectively store published properties?

@ab - I found what FPC implementation of mORMot.TPropInfo.IsStored is incompleate for FPC compiler (handle only consts). Please apply a 80 pull request to fix a problem

Offline

#12 2018-02-06 18:04:27

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

Re: TSQLRecord: is there a way to selectively store published properties?

Has just been fixed as part of https://synopse.info/fossil/info/e58267d974

Offline

#13 2018-02-06 20:09:57

mpv
Member
From: Ukraine
Registered: 2012-03-24
Posts: 1,544
Website

Re: TSQLRecord: is there a way to selectively store published properties?

I have already checked your changes - all work as expected. Thanks!
P.S. - I deleted already merged branches from github

Last edited by mpv (2018-02-06 20:16:03)

Offline

Board footer

Powered by FluxBB