You are not logged in.
Hi,
I have following example classes:
TSQLNamesRecord = class(TSQLRecord)
private
FName: RawUTF8;
published
property Name: RawUTF8 read FName write FName stored AS_UNIQUE;
end;
TSQLCountryRecord = class(TSQLRecordNoCase)
private
FCoutryName: RawUTF8;
published
property CountryName: RawUTF8 read FCoutryName write FCoutryName stored AS_UNIQUE;
end;
TSQLAddressRecord = class(TSQLRecordNoCase)
private
FAddress: RawUTF8;
FCountry: TSQLCountryRecord;
published
property Address: RawUTF8 read FAddress write FAddress;
property Country: RawUTF8 read FCountry write FCountry;
end;
TSQLClientsRecord = class(TSQLRecord)
private
FName: TSQLNamesRecord;
FAddress: TSQLAddressRecord;
published
property ClientName: TSQLNamesRecord read FName write FName;
property ClientAddress: TSQLAddressRecord read FAddress write FAddress;
end;
Now I want to delete the TSQLClientsRecord for a given Name and it should also delete the relevant data including TSQLAddressRecord and TSQLCountryRecord if no other client has the same address.
Is there a way to realize that with the framework by ORM? I think that's what TRecordReferenceToBeDeleted does but I don't find any example. In which of the above classes do I need to put it? And do I need to always set/update it when a new client uses an existing unique value?
Or is the only way be writing an own SQL query for it and put it into ExecuteFmt?
Thanks in advance!
Offline
No one has an idea?
Offline
I'd like to help, but I haven't faced such tasks earlier. Can you explain, please, why do you need to check and clean all dictionaries after every single Client removing? Some kind of storage space economy?
Maybe, in this case, it is more reasonable to make a separate server-side procedure for cleaning dictionaries, which will be scheduled once a week/month/year, for example.
Tell me, please, if I understood you wrong.
btw,
TSQLAddressRecord = class(TSQLRecordNoCase) private FAddress: RawUTF8; FCountry: TSQLCountryRecord; published property Address: RawUTF8 read FAddress write FAddress; property Country: RawUTF8 read FCountry write FCountry; end;
I think you have mistyped here a bit. Published Country property should be also TSQLCountryRecord type, I guess
Offline
Can you explain, please, why do you need to check and clean all dictionaries after every single Client removing? Some kind of storage space economy?
Not really space, just to have a 'clean' dataset without any not used (bloat) values.
Depending on what to save it might be also a thing of privacy reasons if someone requests to delete all his data...but my app runs local, therefore no shared server/data.
Maybe, in this case, it is more reasonable to make a separate server-side procedure for cleaning dictionaries, which will be scheduled once a week/month/year, for example.
What do you mean by this? And how would it be done? By writing own SQL code? But as I use TSQLRestClientDB I don't have any running server, its just a local database for the program which should not contain any garbage/old/unused data.
I think you have mistyped here a bit. Published Country property should be also TSQLCountryRecord type, I guess
Yes, right. Must be
FCountry: TSQLCountryRecord;
published
property Country: TSQLCountryRecord read FCountry write FCountry;
end;
Offline
What do you mean by this? And how would it be done? By writing own SQL code? But as I use TSQLRestClientDB I don't have any running server, its just a local database for the program which should not contain any garbage/old/unused data.
I meant making some procedure to run in a separate thread, which will run periodically and service DB.
Btw, TSQLRestClientDB creates TSQLRestServerDB, so technically you have running server But it doesn't matter.
From my point of view, dictionaries shouldn't contain any personal information... And everything really personal, concerning a client (including address, but you will need to change your model slightly), can be deleted cascaded by reference to Client table, using T{ClassName}ToBeDeletedID or TRecordReferenceToBeDeleted. See 5.1.8 - 5.1.10 of docs: https://synopse.info/files/html/Synopse … l#TITLE_71 . It seems rather clear to me, although I do not use these options - customers usually don't like the ability to purge any information irretrievably.
Just try to use it following docs, and if you'll have troubles, tell me - I'll try to use it by myself and provide you the code. Or maybe somebody will provide you a sample
Offline
I've read the documentation several times already and I also figured out that I need:
TSQLClientsRecord = class(TSQLRecord)
private
FName: TSQLNamesRecord;
FNameReference: TRecordReferenceToBeDeleted;
FAddress: TSQLAddressRecord;
FAddressReference: TRecordReferenceToBeDeleted;
published
property ClientName: TSQLNamesRecord read FName write FName;
property ClientAddress: TSQLAddressRecord read FAddress write FAddress;
property ClientNameReference: TRecordReferenceToBeDeleted read FNameReference write FNameReference;
property ClientAddressReference: TRecordReferenceToBeDeleted read FAddressReference write FAddressReference;
end;
which ends in laborious code as I now also need
ClientNameReference := ClientName.ID;
ClientAddressReference := ClientAddress.ID;
when inserting something.
But it does not delete the row in TSQLClientsRecord, instead it sets the reference value to 0 for the Name where it deleted to row from the Names table. Latter is what I want but it should also delete TSQLAddressRecord row and TSQLCountryRecord row if it's not used for any other TSQLAddressRecord entry.
Offline
it should also delete TSQLAddressRecord row and TSQLCountryRecord row if it's not used for any other TSQLAddressRecord entry.
It is not a cascade deletion (some kind of opposite deletion), so, unfortunately, you will have to make it by your hands, I guess...
Offline
@Vitaly
Thanks for your help.
I'm still unsure if the code
TSQLClientsRecord = class(TSQLRecord)
private
FName: TSQLNamesRecord;
FNameReference: TRecordReferenceToBeDeleted;
FAddress: TSQLAddressRecord;
FAddressReference: TRecordReferenceToBeDeleted;
published
property ClientName: TSQLNamesRecord read FName write FName;
property ClientAddress: TSQLAddressRecord read FAddress write FAddress;
property ClientNameReference: TRecordReferenceToBeDeleted read FNameReference write FNameReference;
property ClientAddressReference: TRecordReferenceToBeDeleted read FAddressReference write FAddressReference;
end;
is as it should be done with mORMot framework.
Both, the normal property and the reference, contain the same ID - it only added additional foreign keys for the references. So couldn't I remove the extra reference in the ClientsRecord?
The help also mentions TSQLRecordClassName[ToBeDeleted]ID but I got no idea how I can use TSQLNamesRecordToBeDeletedID / TSQLAddressRecordToBeDeletedID because both are not defined. The help says it can delete in one table, which is what I need as shown above.
Does it also need an extra reference?
Offline
As far as I understand, you could use smth like this (following your naming):
TSQLNamesRecord = class(TSQLRecord)
...
end;
TSQLNamesRecordToBeDeletedID = type TID;
TSQLAddressRecord= class(TSQLRecord)
...
end;
TSQLAddressRecordToBeDeletedID = type TID;
TSQLClientsRecord = class(TSQLRecord)
private
FName: TSQLNamesRecordToBeDeletedID;
FAddress: TSQLAddressRecordToBeDeletedID;
published
property ClientName: TSQLNamesRecordToBeDeletedID read FName write FName;
property ClientAddress: TSQLAddressRecordToBeDeletedID read FAddress write FAddress;
end;
So, if any Name (or Address) record is deleted, all Clients records, which use this particular Name (or Address) ID, also will be removed.
But again, I afraid, that it is not what were you looking for in previous messages. Hope, I'm wrong
Offline
Found out that I don't need any extra reference because TSQLRecord also resets the ID to 0 and as I only have one table it's enough. :-)
Offline
I Agree with @Vitaly,
The TSQLXYZRecordToBeDeletedID does the opposite of what you are looking for.
Deleting an Address deletes clients that use it.
Offline