Custom Storage -- Cache 5
Transcript of Custom Storage -- Cache 5
![Page 1: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/1.jpg)
Mapping Existing Globals to Objects and SQLMike LaRoccaInterSystems Corporation
![Page 2: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/2.jpg)
AgendaAgenda
CacheStorageCacheStorageCacheStorageCacheStorage
Storage Strategy OverviewStorage Strategy OverviewStorage Strategy OverviewStorage Strategy Overview
CacheSQLStorageCacheSQLStorageCacheSQLStorageCacheSQLStorage
CustomStorageCustomStorageCustomStorageCustomStorage
CacheSQLStorage ExampleCacheSQLStorage Example CacheSQLStorage ExampleCacheSQLStorage Example
![Page 3: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/3.jpg)
Storage Strategy ComparisonsStorage Strategy Comparisons
CacheStorageCacheStorage CacheSQLStorageCacheSQLStorage CustomStorageCustomStorage
SQLSQL ObjectsObjects
Automatically provided by CachAutomatically provided by Caché
Manually provided by database designerManually provided by database designer
![Page 4: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/4.jpg)
• CacheStorage is ideal for brand new applications
• CacheSQLStorage is typically used where existing global structures can be expressed relationally, and Object access can be code-generated based on SQL statements
• CustomStorage is used when existing global structures can or cannot be expressed relationally, and complex logic must be used to provide Object access
Choosing Your Storage StrategyChoosing Your Storage Strategy
![Page 5: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/5.jpg)
AgendaAgenda
CacheStorageCacheStorageCacheStorageCacheStorage
Storage Strategy OverviewStorage Strategy OverviewStorage Strategy OverviewStorage Strategy Overview
CacheSQLStorageCacheSQLStorageCacheSQLStorageCacheSQLStorage
CustomStorageCustomStorageCustomStorageCustomStorage
CacheSQLStorage ExampleCacheSQLStorage Example CacheSQLStorage ExampleCacheSQLStorage Example
![Page 6: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/6.jpg)
CacheStorage OverviewCacheStorage Overview
Object APIObject API
ApplicationApplicationApplicationApplication
%LoadData%LoadData%LoadData%LoadData %SaveData%SaveData%SaveData%SaveData %DeleteData%DeleteData%DeleteData%DeleteData
ObjectScriptObjectScriptObjectScriptObjectScript ObjectScriptObjectScriptObjectScriptObjectScript ObjectScriptObjectScriptObjectScriptObjectScript Object Object ImplementationImplementation
GlobalsGlobalsGlobalsGlobals
![Page 7: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/7.jpg)
• CacheStorage generates list-based global structures
• The unique identifier (IDKey / PrimaryKey) can be automatically generated or supplied by the application
• This influences what the global subscripts look like
• The list-based data can be re-ordered
• This influences what the global values look like
CacheStorage NotesCacheStorage Notes
![Page 8: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/8.jpg)
AgendaAgenda
CacheStorageCacheStorageCacheStorageCacheStorage
Storage Strategy OverviewStorage Strategy OverviewStorage Strategy OverviewStorage Strategy Overview
CacheSQLStorageCacheSQLStorageCacheSQLStorageCacheSQLStorage
CustomStorageCustomStorageCustomStorageCustomStorage
CacheSQLStorage ExampleCacheSQLStorage Example CacheSQLStorage ExampleCacheSQLStorage Example
![Page 9: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/9.jpg)
CacheSQLStorage OverviewCacheSQLStorage Overview
Object APIObject API
ApplicationApplicationApplicationApplication
%LoadData%LoadData%LoadData%LoadData %SaveData%SaveData%SaveData%SaveData %DeleteData%DeleteData%DeleteData%DeleteData
SELECTSELECTSELECTSELECT INSERT / INSERT / UPDATEUPDATEINSERT / INSERT / UPDATEUPDATE DELETEDELETEDELETEDELETE SQL SQL
ImplementationImplementation
GlobalsGlobalsGlobalsGlobals
![Page 10: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/10.jpg)
• Create a Persistent Class
• Add properties to your new class
• Figure out which property (or properties) will be your unique identifier (IDKey / Primary Key) for the class
• Create a storage strategy, mapping your class properties to your global data
CacheSQLStorage Mapping –CacheSQLStorage Mapping –A Bird’s Eye ViewA Bird’s Eye View
![Page 11: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/11.jpg)
• CacheSQLStorage maps are typically created by:
• A programmer / database designer
• F-DBMS conversion program
• KB-SQL conversion program
CacheSQLStorage MapsCacheSQLStorage Maps
![Page 12: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/12.jpg)
• Not all global structures can be easily mapped for full Read/Write/Delete access
• Many table mappings of legacy global structures are for SELECT only
• If full update access is also required, some additional work outside of the “typical” mapping requirements might be necessary
What Type of SQL Access is Allowed?What Type of SQL Access is Allowed?
![Page 13: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/13.jpg)
• CacheSQLStorage maps come in a few flavors:
• Data (aka MasterMap): All fields must be represented here
• Index: A subset of fields are represented here
• Full (default): All data is populated within the index
• Conditional: Data is populated only if a condition is satisfied
• Nonnull: Null values are not populated within the index
Map TypesMap Types
![Page 14: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/14.jpg)
• IDKey indexes declare the unique identifier for objects
• Primary Key indexes declare the unique identifier for SQL
• IDKeys and Primary Keys are typically based on the same field(s)
Mapping Concepts: ID / Primary KeysMapping Concepts: ID / Primary Keys
![Page 15: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/15.jpg)
• Map subscripts are typically equivalent to global subscripts
• Types of subscript access supported:Sub: Based on a “standard” global subscript
Piece: Based on a certain position, using a delimiter
Global: Based on data stored in multiple globals
Other: Based on user-written code
Mapping Concepts: SubscriptsMapping Concepts: Subscripts
![Page 16: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/16.jpg)
• There’s a close relationship between the IDKey and the RowID for data maps, but not necessarily for index maps
• A RowID is used to uniquely identify data in a global, based on the subscripts defined in the map defintion
• For example, if our global structure was this:
^Person(PersonID,“Cars”,CarID)=“Make^Model^Year”
We would have 2 fields in our RowID:
PersonID: Stored in level 1 of the global, or {L1}
CarID: Stored in level 3 of the global, or {L3}
Mapping Concepts: RowIDsMapping Concepts: RowIDs
![Page 17: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/17.jpg)
• Once subscripts mappings are defined, the next step is to map fields to a specific location in the global
• Additional subscript nodes (literals only) can be defined
• Data can be positioned within a string according to a given delimiter or list element
Mapping Concepts: Data FieldsMapping Concepts: Data Fields
![Page 18: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/18.jpg)
• Map Name: Must begin with a letter, proceeded by alpha-numeric
• Map Type: Data or Index
• Global Name: Name of global with ^ in front, or local array
• Node Structure: $Piece (typical) or $List (introduced in Caché 2.1)
• Population Type: Define how the map will be populated
• Population %: Estimate percentage of number of rows in this index
• Condition: Expression which defines the condition, such as {Name}‘=“”
• Conditional Fields: Field(s) on which the condition is tested
• Conditional with hostvars: Boolean which influences cached queries’ use of index
• Row Reference: Allows programmers to override the generated RowID
Map Editor: DetailMap Editor: Detail
![Page 19: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/19.jpg)
• Access Type: Sub, Piece, Global, or Other
• Delimiter: Only used if Access Type is Piece
• Expression: Typically the {field}, “string” or numeric literal, or delimited position
• Loop Init Value: Non-inclusive value used in generated traversal code
• Start Value: Inclusive value used in generated traversal code
• Stop Value: Literal value at which traversal code should terminate
• Stop Expression: Expression used to terminate traversal code, such as {L1}>200
• Data Access: Override the context of the current access-level’s value expression
• Next Code: Used by programmers to override generated traversal code
• Invalid Conditions: Expression used to filter rows out of the map, such as {L1}<1
• Access Variables: Variables used by programmer, guaranteed to have unique names
Subscript Editor: DetailSubscript Editor: Detail
![Page 20: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/20.jpg)
• RowID: Position a field has within the full RowID specification
• Field: Name of the field that makes up this part of the RowID
• Expression: The level within the subscript definition, such as {L2} or {L6}
RowID Editor: DetailRowID Editor: Detail
![Page 21: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/21.jpg)
• Field: Name of the field being mapped on the right-side of = sign
• Node: An additional subscript (literal only) where this field exists
• Piece: Position in the string using the supplied delimiter
• Delimiter: Specifies which delimiter to use, such as “^” or $c(1)
Data Editor: DetailData Editor: Detail
![Page 22: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/22.jpg)
AgendaAgenda
CacheStorageCacheStorageCacheStorageCacheStorage
Storage Strategy OverviewStorage Strategy OverviewStorage Strategy OverviewStorage Strategy Overview
CacheSQLStorageCacheSQLStorageCacheSQLStorageCacheSQLStorage
CustomStorageCustomStorageCustomStorageCustomStorage
CacheSQLStorage ExampleCacheSQLStorage Example CacheSQLStorage ExampleCacheSQLStorage Example
![Page 23: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/23.jpg)
CustomStorage OverviewCustomStorage Overview
Object APIObject API
ApplicationApplicationApplicationApplication
%LoadData%LoadData%LoadData%LoadData %SaveData%SaveData%SaveData%SaveData %DeleteData%DeleteData%DeleteData%DeleteData
???? ???? ????Custom Custom
ImplementationImplementation
GlobalsGlobalsGlobalsGlobals
![Page 24: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/24.jpg)
• Create a Persistent Class
• Add properties to your new class
• Figure out which property (or properties) will be your unique identifier (IDKey / Primary Key) for the class
• Create a storage strategy, mapping your class properties to your global data
• Implement the Object access code, namely: %LoadData, %SaveData, %DeleteData
CustomStorage Mapping –CustomStorage Mapping –A Bird’s Eye ViewA Bird’s Eye View
![Page 25: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/25.jpg)
• In order to use SQL with CustomStorage, you must define a special parameter within your class:
Parameter SQLENABLED = 1;
• Mapping the SQL portion with CustomStorage is identical to the methods used for CacheSQLStorage
CustomStorage and SQLCustomStorage and SQL
![Page 26: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/26.jpg)
• In order to use Objects with CustomStorage, you must do the following:
• Implement %LoadData, %SaveData, %DeleteData
• Within your code, you must manage:• Object IDs on disk and in memory (via the %IdSet() method)
• Property instance variables (property names with “i%” in front)
• Concurrency
• Data uniqueness
• Foreign key constraints
CustomStorage and ObjectsCustomStorage and Objects
![Page 27: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/27.jpg)
• Code implemented by %LoadData() will be executed each time an object is loaded, typically from %Open() and %OpenId()
• %LoadData example:
Method %LoadData(id As %Library.String) As %Library.Status
{Set i%SSN = id
Set i%Name = $Piece(^P(id),“^”,1)
Set i%DOB = $Piece(^P(id),“^”,2)
Quit $$$OK
}
%LoadData%LoadData
![Page 28: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/28.jpg)
• Code implemented by %SaveData() will be executed each time an object is saved by calling the %Save() method
• %SaveData Example: Method %SaveData(id As %Library.String) As %Library.Status
{Lock ^P(id):5 If '$Test Quit $$$ERROR($$$LockFailedToAcquireExclusive)
Set id = i%SSNDo ..%IdSet(id)
Set $Piece(^P(id),”^”,1) = i%NameSet $Piece(^P(id),”^”,2) = i%DOB
Quit $$$OK}
%SaveData%SaveData
![Page 29: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/29.jpg)
• Code implemented by %DeleteData will be executed each time an object is deleted, by calling %Delete() or %DeleteId()
• %DeleteData example:
Method %DeleteData(id As %String, concurrency as %Integer) As %Status
{Lock ^P(id):5 If '$Test Quit $$$ERROR($$$LockFailedToAcquireExclusive)
Kill ^P(id)
Quit $$$OK
}
%DeleteData%DeleteData
![Page 30: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/30.jpg)
AgendaAgenda
CacheStorageCacheStorageCacheStorageCacheStorage
Storage Strategy OverviewStorage Strategy OverviewStorage Strategy OverviewStorage Strategy Overview
CacheSQLStorageCacheSQLStorageCacheSQLStorageCacheSQLStorage
CustomStorageCustomStorageCustomStorageCustomStorage
CacheSQLStorage ExampleCacheSQLStorage Example CacheSQLStorage ExampleCacheSQLStorage Example
![Page 31: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/31.jpg)
Phone Phone NumbersNumbers
Phone Phone NumbersNumbers Doctor VisitsDoctor VisitsDoctor VisitsDoctor Visits
Example Data ModelExample Data Model
• Two Parent-Children relationships exist:
• A Patient can have many phone numbers
• A Patient can have many doctor visits
• Deleting a patient should delete all related phone numbers & visits
AddressAddressAddressAddressPatientPatient
![Page 32: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/32.jpg)
^P(SSN) = “Name^DOB^Phone1~Phone2~...~PhoneN^Company”
^P(SSN,“Address”) = “City^PostalCode^Country”
^P(SSN,“Visits”,VisitDate,VisitTime) = “Symptom^Payment”
Example Data Global StructureExample Data Global Structure
^P(“211-22-1222”) = “Smith,John^39873^718-317-3312~917-225-2213^AT&T”
^P(“211-22-1222”,“Address”) = “New York^10312^USA”
^P(“211-22-1222”,“Visits”,58809,43200) = “Cough^15.00”
^P(“211-22-1222”,“Visits”,58820,57900) = “Sore Throat^50.00”
![Page 33: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/33.jpg)
^PI(Name,SSN) = “”
Example Index Global StructureExample Index Global Structure
^PI(“Smith,John”,“211-22-1222”) = “”
![Page 34: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/34.jpg)
Create a Persistent ClassCreate a Persistent Class
![Page 35: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/35.jpg)
Add PropertiesAdd Properties
![Page 36: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/36.jpg)
Choose a Unique IdentifierChoose a Unique Identifier
• Our identifier will be based on 1 field: SSN
![Page 37: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/37.jpg)
Declare an ID / Primary Key IndexDeclare an ID / Primary Key Index
• Base this index on the SSN property
• Don’t modify the index collation
![Page 38: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/38.jpg)
Create a Storage DefinitionCreate a Storage Definition
![Page 39: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/39.jpg)
Create a Data MapCreate a Data Map
• Map names cannot have spaces
![Page 40: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/40.jpg)
Define the Global SubscriptsDefine the Global Subscripts
• Subscript level 1 is based on SSN
![Page 41: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/41.jpg)
Define the Row IDDefine the Row ID
• Row ID 1 is based on SSN in subscript level 1
![Page 42: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/42.jpg)
Define the Property MappingsDefine the Property Mappings
• Enter delimiter and additional node information
![Page 43: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/43.jpg)
Create an Index MapCreate an Index Map
• Choose a population type of ‘full’
![Page 44: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/44.jpg)
Define the Index SubscriptsDefine the Index Subscripts
![Page 45: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/45.jpg)
Define the Index Row IDDefine the Index Row ID
• Row ID 1 is based on SSN in subscript level 2
![Page 46: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/46.jpg)
Save and Compile ClassSave and Compile Class
![Page 47: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/47.jpg)
Create a PhoneList Child TableCreate a PhoneList Child Table
• This class will also be persistent
![Page 48: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/48.jpg)
Create the Parent-Child RelationshipCreate the Parent-Child Relationship
• Relationships are special types of properties
• In addition to naming the property in this class (PatientRef here), you must also specify the inverse side of the relationship (PhoneNumbers here)
![Page 49: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/49.jpg)
Add Additional PropertiesAdd Additional Properties
• In addition to defining a phone number, we must also define a property to represent the position within the embedded delimited string (Counter here)
![Page 50: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/50.jpg)
Choose a Unique IdentifierChoose a Unique Identifier
• Our identifier will be based on 1 field: Counter
![Page 51: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/51.jpg)
Declare an ID / Primary Key IndexDeclare an ID / Primary Key Index
• Base this index on the Counter property
• Don’t modify the index collation
• The PatientRef property is implicitly part of the IDKey / Primary Key
![Page 52: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/52.jpg)
Create a Storage DefinitionCreate a Storage Definition
![Page 53: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/53.jpg)
Create a Data MapCreate a Data Map
• Map names cannot have spaces
![Page 54: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/54.jpg)
Define the Global SubscriptsDefine the Global Subscripts
• Subscript level 1 is based on Training.Patient.SSN
• Subscript level 2 is based on the “^” delimiter, using the 3rd position
• Subscript level 3 is based on the “~” delimiter, using Counter for position
![Page 55: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/55.jpg)
Define the Row IDDefine the Row ID
• Row ID 1 is based on Training.Patient.SSN in subscript level 1
• Row ID 2 is based on Counter in subscript level 3
![Page 56: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/56.jpg)
Define the Property MappingsDefine the Property Mappings
• Here, you can enter HomePhone with no additional specifications
![Page 57: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/57.jpg)
Save and Compile ClassSave and Compile Class
![Page 58: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/58.jpg)
Create a Visit Child TableCreate a Visit Child Table
• This class will also be persistent
![Page 59: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/59.jpg)
Create the Parent-Child RelationshipCreate the Parent-Child Relationship
• In addition to naming the property in this class (PatientRef here), you must also specify the inverse side of the relationship (Visits here)
![Page 60: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/60.jpg)
Add Additional PropertiesAdd Additional Properties
![Page 61: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/61.jpg)
Choose a Unique IdentifierChoose a Unique Identifier
• This time, our identifier will be based on 2 fields: VisitDate and VisitTime
![Page 62: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/62.jpg)
Declare an ID / Primary Key IndexDeclare an ID / Primary Key Index
• Base this index on the VisitDate and VisitTime properties
• Don’t modify the index collation
• The PatientRef property is implicitly part of the IDKey / Primary Key
![Page 63: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/63.jpg)
Create a Storage DefinitionCreate a Storage Definition
![Page 64: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/64.jpg)
Create a Data MapCreate a Data Map
• Map names cannot have spaces
![Page 65: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/65.jpg)
Define the Global SubscriptsDefine the Global Subscripts
• Subscript level 1 is based on Training.Patient.SSN• Subscript level 2 is a string literal: “Visits”• Subscript level 3 is based on VisitDate• Subscript level 4 is based on VisitTime
![Page 66: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/66.jpg)
Define the Row IDDefine the Row ID
• Row ID 1 is based on Training.Patient.SSN in subscript level 1• Row ID 2 is based on VisitDate in subscript level 3• Row ID 3 is based on VisitTime in subscript level 4
![Page 67: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/67.jpg)
Define the Property MappingsDefine the Property Mappings
![Page 68: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/68.jpg)
Save and Compile ClassSave and Compile Class
![Page 69: Custom Storage -- Cache 5](https://reader036.fdocuments.net/reader036/viewer/2022081507/5517c038497959a8308b4cae/html5/thumbnails/69.jpg)
Mapping Existing Globals to Objects and SQLMike LaRoccaInterSystems Corporation