While the classic solution followed rather close the concepts and design of the ancestors
Caché / IRIS allows a more modern approach to flexible/multidimensional properties
Let's see our demo class as before:
{
Property Name As %String;
Property DOB As %Date;
Property mJSON As %DynamicObject;
/// Property Multi As %String [ MultiDimensional ];
The JSON object allows us all the flexibility you may need
with the key-value paradigm as a basic concept.
The storage map honors this with a suitable entry.
{
<Data name="MultiDefaultData">
<Value name="1">
<Value>Name</Value>
</Value>
<Value name="2">
<Value>DOB</Value>
</Value>
</Data>
<Data name="mJSON">
<Attribute>mJSON</Attribute>
<Structure>node</Structure>
<Subscript>"mJSON"</Subscript>
</Data>
<DataLocation>^DC.MultiD</DataLocation>
<DefaultData>MultiDefaultData</DefaultData>
<IdLocation>^DC.MultiD</IdLocation>
<IndexLocation>^DC.MultiI</IndexLocation>
<StreamLocation>^DC.MultiS</StreamLocation>
<Type>%Storage.Persistent</Type>
}
Diagnosis: The storage generator has already foreseen the structure we had previously to add manually.
Issue #1) doesn't exist anymore
The same for issue #2) no extra fiddling for SQL. Access out of the box.
I admit, my fantasy for test data was rather limited.
So what's the price for this improvement ?
Instead of: Set obj.Multi("robert")="rcc"
it is now : Do obj.mJSON.%Set("robert","rcc")
a substructure comparable to obj.Multi("robert",1) might require a dynamic array
instead of navigation by $order() and $query() you now use an iterator and operate full JSON compatible.
retrieving data by set var=obj.Multi("robert")
or similar changes to set var=obj.mJSON.%Get("robert")
Personally I find this a much cleaner approach and it is independent of registered or persistent objects
Interesting solution - I keep it