Skip to content

Kitto.Store

Kitto's in-memory data store, holding record sets between the database and the UI/serialization layers. Defines TKStore (a record container with a header, key and change tracking), TKRecords (its record collection), TKRecord (a single row with New/Clean/Dirty/Deleted state and optional detail stores), TKField (a typed value with modified tracking and JSON/XML rendering) and the supporting header and key node classes. All classes are built on the EF.Tree node model.

TKKeyField class

A single field of a key definition (TKKey), identified by name.

pascal
property Key: TKKey read GetKey;

The key this field belongs to.

pascal
property FieldName: string read GetFieldName;

The name of the field.

TKKey class

Ordered set of fields that make up a store/record key.

pascal
property Fields[I: Integer]: TKKeyField read GetField;

The key fields, by index (default property).

pascal
property FieldCount: Integer read GetFieldCount;

Number of fields that make up the key.

pascal
procedure SetFieldNames(const AFieldNames: TStringDynArray);

Defines the key by the given field names (rebuilds the child fields).

pascal
function GetFieldNames: TStringDynArray;

Returns the key's field names, in order.

TKField class

A single typed field value within a TKRecord. Wraps an EF.Tree node, tracks its modified state, resolves its datatype and name from its TKHeaderField, and renders itself as a JSON or XML value.

pascal
procedure Assign(const ASource: TEFTree;

Copies value and header from ASource (another TKField).

pascal
property HeaderField: TKHeaderField read FHeaderField write FHeaderField;

The header field describing this field's metadata (name, datatype).

pascal
procedure MarkAsUnmodified;

Clears the modified flag (IsModified := False).

pascal
procedure SetToNull(const AForceChangeNotification: Boolean = False);

Sets the value to Null; AForceChangeNotification fires the change event even if already null.

pascal
property IsModified: Boolean read FIsModified;

True if the value changed since load / MarkAsUnmodified.

pascal
property ParentRecord: TKRecord read GetParentRecord;

The record that owns this field.

pascal
function GetAsJSON(const AForDisplay: Boolean): string;

The field as a JSON "name":value pair ('' if the datatype has no JSON form).

pascal
function GetAsJSONValue(const AForDisplay: Boolean;

The field value as a JSON literal (optionally quoted; nulls as '' or null).

pascal
function GetAsXML(const AForDisplay: Boolean): string;

The field as an XML element.

pascal
function GetAsXMLValue(const AForDisplay: Boolean;

The field value formatted for XML.

pascal
property FieldName: string read GetFieldName;

The field's name.

pascal
function IsCompositeField: Boolean;

True if this field aggregates several physical sub-fields.

pascal
function IsPartOfCompositeField: Boolean;

True if this field is a sub-field of a composite field.

pascal
procedure SetTransientProperty(const APropertyName: string;

Sets a transient (non-persisted) property on the field, e.g. a UI hint.

TKRecord class

A single record (row) held by a store. Owns its TKField children, tracks its persistence state (New/Clean/Dirty/Deleted) driving the save instruction, supports value backup/restore, optional detail (child) stores, and JSON/XML rendering.

pascal
procedure AfterConstruction;

Initializes the record in the New state.

pascal
destructor Destroy;

Frees the record's detail stores and value backup.

pascal
procedure FieldChanging(const AField: TKField;

Fires before a field value changes; a handler may alter ANewValue or veto via ADoIt.

pascal
procedure FieldChanged(const AField: TKField;

Fires after a field value changed; drives reference cascade and OnFieldChange.

pascal
property State: TKRecordState read FState;

Persistence state (New/Clean/Dirty/Deleted) driving the SaveRecord instruction.

pascal
procedure RestorePreviousState;

Restores the state captured before the last state change.

pascal
property Records: TKRecords read GetRecords;

The record collection (TKRecords) this record belongs to.

pascal
property Store: TKStore read GetStore;

The store owning this record.

pascal
property Key: TKKey read GetKey;

The record's key (the key fields with their current values).

pascal
property Fields[I: Integer]: TKField read GetField;

The record's fields, by index (default property).

pascal
property FieldCount: Integer read GetFieldCount;

Number of fields in the record.

pascal
function FindField(const AFieldName: string): TKField;

Returns the field with the given name, or nil if absent.

pascal
function FieldByName(const AFieldName: string): TKField;

Returns the field with the given name; raises if absent.

pascal
procedure EnumFields(const AProc: TFunc<TKField, Boolean>);

Calls AProc for each field until it returns False.

pascal
function MatchesValues(const AValues: TEFNode): Boolean;

True if every field in AValues matches this record's value for the same name.

pascal
procedure HandleSetToNullInstructions;

Applies the deferred "set to null" instructions collected during editing.

pascal
procedure ReadFromFields(const AFields: TFields;

Reads field values from the current dataset record, applying field name translation by calling TranslateFieldName. If AByIndex is True, field values are copied by index instead of by name.

pascal
procedure ReadFromNode(const ANode: TEFNode);

Reads any values from the specified node by name. Fields whose names are not in the passed node are set to Null.

pascal
function GetAsJSON(const AForDisplay: Boolean;

The record as a JSON object {field:value,…}; AFieldFilterFunc can exclude fields.

pascal
function GetAsXML(const AForDisplay: Boolean;

The record as an XML element; AFieldFilterFunc can exclude fields.

pascal
procedure ExpandExpression(var AExpression: string);

Replaces occurrencess of {FieldName} tags in the specified string with actual field values, formatted as strings.

pascal
procedure MarkAsNew;

Marks the record as new. An insert instruction will be executed when persisting it.

pascal
procedure MarkAsModified;

Marks the record as dirty unless it's already new or deleted.

pascal
procedure MarkAsDeleted;

Marks the record as deleted. A delete instruction will be executed when persisting it.

pascal
procedure MarkAsClean;

Marks the record as clean. No instructions will be performed when persisting it.

pascal
property IsNew: Boolean read GetIsNew;

True if the record is marked New (will be inserted on save).

pascal
property IsDeleted: Boolean read GetIsDeleted;

True if the record is marked Deleted (will be deleted on save).

pascal
property DetailStoreCount: Integer read GetDetailStoreCount;

Number of detail (child) stores attached to this record.

pascal
property DetailStores[I: Integer]: TKStore read GetDetailsStore;

The detail (child) stores, by index.

pascal
function AddDetailStore(const AStore: TKStore): TKStore;

Attaches a detail store to this record and returns it.

pascal
function GetDetailStoreList: TObjectList<TKStore>;

Returns the internal detail store list. Use with care — needed for temporarily detaching detail stores during master-only save.

pascal
procedure Backup;

Saves a copy of the current values, for a later Restore.

pascal
procedure Restore;

Restores the values saved by the last Backup.

pascal
procedure ClearBackup;

Frees the copy taken by Backup. Called on the success path of a Backup/try/except-Restore block: Restore only ever runs in that same except, so once the block completes the backup - a full copy of the record - would otherwise stay in memory for the record's whole life.

pascal
function ChangesPending: Boolean;

True if the record (or any detail store) has unsaved changes.

pascal
property OnFieldChange: TKFieldChangeEvent read FOnFieldChange write FOnFieldChange;

Fired after a field value changes; used to run AfterFieldChange rules.

pascal
function AddField(const AHeaderField: TKHeaderField): TKField;

Adds a field for the given header field and returns it.

pascal
function GetFieldValues(const AFieldNames: TStringDynArray): Variant;

Returns a variant array with an item for each requested field value. Raises exceptions if fields are not found.

pascal
function GetFieldValuesAsString(const AFieldNames: TStringDynArray;

Returns a concatenation field values using the specified separator. Raises exceptions if fields are not found.

pascal
procedure SetTransientProperty(const ASubjectType, ASubjectName, APropertyName: string;

Sets a transient (non-persisted) property on a subject (field/record), notifying OnSetTransientProperty.

pascal
property OnSetTransientProperty: TProc<string, string, string, Variant> read FOnSetTransientProperty write FOnSetTransientProperty;

Callback invoked by SetTransientProperty (subjectType, subjectName, property, value).

TKRecords class

The collection of records held by a TKStore, sharing a common key.

pascal
procedure AfterConstruction;

Creates the record collection's key object.

pascal
destructor Destroy;

Frees the record collection's key object.

pascal
procedure Clear;

Removes and frees all records.

pascal
property Store: TKStore read GetStore;

The store owning this record collection.

pascal
property Key: TKKey read FKey write SetKey;

The key definition shared by the records.

pascal
function FindRecord(const AValues: TEFNode): TKRecord;

Returns the record matching the key values in AValues, or nil.

pascal
function GetRecord(const AValues: TEFNode): TKRecord;

Returns the record matching the key values in AValues; raises if absent.

pascal
property Records[I: Integer]: TKRecord read GetRecordByIndex;

The records, by index (default property).

pascal
property RecordCount: Integer read GetRecordCount;

Total number of records (including deleted).

pascal
function GetRecordCount(const APredicate: TFunc<TKRecord, Boolean>): Integer;

Number of records for which APredicate returns True.

pascal
procedure EnumRecords(const AFrom, AFor: Integer;

Calls AProc for the records in [AFrom, AFrom+AFor) that satisfy APredicate.

pascal
function EnumAllRecords(ARecord: TKRecord): Boolean;

Predicate for EnumRecord. Allows all records, including deleted ones.

pascal
function EnumNonDeletedRecords(ARecord: TKRecord): Boolean;

Predicate for EnumRecord. Allows all records, except deleted ones.

pascal
function Append: TKRecord;

Appends a new (empty) record and returns it.

pascal
function AppendAndInitialize: TKRecord;

Appends a new record, applies the header (creates its fields) and returns it.

pascal
procedure Remove(const ARecord: TKRecord);

Removes and frees the given record (no DB effect).

pascal
function GetAsJSON(const AForDisplay: Boolean;

The records as a JSON array [{…},…]; AFrom/AFor page, AFieldFilterFunc filters fields.

pascal
function GetAsXML(const AForDisplay: Boolean;

The records as XML; AFrom/AFor page, AFieldFilterFunc filters fields.

pascal
procedure ForEach(const AProc: TProc<TKRecord>);

Calls AProc for every record (including deleted).

pascal
procedure Sort(const ACompareFunc: TKRecordCompareFunc);

Sorts the records by calling the specified compare function.

pascal
procedure MarkAsClean;

Marks all records as clean (no pending changes).

TKHeaderField class

A field definition in a store header (its name and datatype).

pascal
property FieldName: string read GetFieldName;

The field's name.

TKHeader class

Describes the fields of a store (name + datatype). Apply creates the matching field nodes on a record.

pascal
procedure Apply(const ARecord: TKRecord);

Adds to ARecord one field node with no name and the correct datatype for each header field.

Names are not set in all records in order to save space. Fields are meant to be accessed by name in the header and by position in records.

pascal
property FieldCount: Integer read GetFieldCount;

Number of fields defined in the header.

pascal
property Fields[I: Integer]: TKHeaderField read GetField;

The header fields, by index.

pascal
function AddField(const AFieldName: string): TKHeaderField;

Adds a header field with the given name and returns it.

pascal
procedure GetFieldNames(List: TStrings);

Fills List with the header field names, in order.

pascal
function FindField(const AFieldName: string): TKHeaderField;

Returns the header field with the given name, or nil.

pascal
function FieldByName(const AFieldName: string): TKHeaderField;

Returns the header field with the given name; raises if absent.

TKStore class

In-memory container of records with a header (field definitions) and a key. Loads records from the database, tracks pending changes, supports predicate-based iteration and aggregation (Count/Sum/Min/Max/Avg), sorting, and JSON/XML rendering.

pascal
destructor Destroy;

Frees the store's header.

pascal
procedure DisableChangeNotifications;

Suspends change notifications (reentrant; pair with EnableChangeNotifications).

pascal
procedure EnableChangeNotifications;

Resumes change notifications suspended by DisableChangeNotifications.

pascal
function ChangeNotificationsEnabled: Boolean;

True if change notifications are currently enabled.

pascal
procedure DoWithChangeNotificationsDisabled(const AProc: TProc);

Runs AProc with change notifications disabled, restoring them afterwards.

pascal
property Key: TKKey read GetKey write SetKey;

The store's key definition.

pascal
property Header: TKHeader read GetHeader;

The header describing the store's fields (name + datatype).

pascal
property Records: TKRecords read GetRecords;

The records held by the store.

pascal
property RecordCount: Integer read GetRecordCount;

Number of records in the store.

pascal
property IsEmpty: Boolean read GetIsEmpty;

True if the store holds no records.

pascal
procedure Load(const ADBConnection: TEFDBConnection;

Loads records by executing ACommandText on ADBConnection (optionally appending).

pascal
procedure Load(const ADBQuery: TEFDBQuery;

Loads records from an already-prepared query (optionally by field index).

pascal
function AppendRecord(const AValues: TEFNode): TKRecord;

Appends a record and fills it with the specified values.

pascal
procedure RemoveRecord(const ARecord: TKRecord);

Removes the record from the store, if present.

Calling this method will NOT trigger any database operation. It is meant to cancel pending changes.

TKRecord.MarkAsDeleted

pascal
function GetAsJSON(const AForDisplay: Boolean;

The store's records as a JSON array; AFrom/AFor page, AFieldFilterFunc filters fields. This is the ready-made store→JSON entry point (view-aware for a TKViewTableStore).

pascal
function GetAsXML(const AForDisplay: Boolean;

The store's records as XML; AFrom/AFor page the result.

pascal
function ChangesPending: Boolean;

True if any record has unsaved changes (new/dirty/deleted).

pascal
procedure Iterate(const AProc: TProc<TKRecord>;

Iterates all records in the store (regardless of state) calling APredicate for each record and then calling AProc when all predicates return True. Use the optional predicate to filter records before passing them to AProc.

Parameters:

  • AProc — A procedure that receives a TKRecord.
  • APredicates — An array of functions that receive a TKRecord and return a Boolean indicating whether to include the record in the enumeration or not. You can pass predefined predicates such as All and NotDeleted or code your own.
pascal
function All: TPredicate<TKRecord>;

Pass this as a predicate to one of the predicate-accepting methods to specify that you want to include all records (including those marked as deleted).

pascal
function ExcludeDeleted: TPredicate<TKRecord>;

Pass this as a predicate to one of the predicate-accepting methods to specify that you want to include all records except those marked as deleted.

pascal
function Count(const APredicates: array of TPredicate<TKRecord>): Integer;

Returns the number of records in which all the specified predicates hold (that is, all return True for a given record).

pascal
function Count(const AFieldName: string;

Returns the number of non-deleted records in which the specified field has the specified value. This is a special case of the more generic predicate-based Count method.

pascal
function Max(const AFieldName: string): Variant;

Maximum value of the given field over non-deleted records.

pascal
function Min(const AFieldName: string): Variant;

Minimum value of the given field over non-deleted records.

pascal
function Sum(const AFieldName: string): Variant;

Sum of the given field over non-deleted records.

pascal
function Avg(const AFieldName: string): Variant;

Average of the given field over non-deleted records.

pascal
procedure Sort(const ACompareFunc: TKRecordCompareFunc);

Sorts the store records by calling the specified compare function.

pascal
function GetRecord(const AKey: TEFTree;

Locates and returns a record from the key values stored in AKey. Raises an exception if the record is not found.

Parameters:

  • AKey — Object containing at least on top-level pair for each key value.
  • AFormatSettings — Used to interpret string values (all pair values are read as string and then converted according to this settings object).
  • ATranslator — Pass a translation function if key names in AKey do not match wanted child node names and you need to translate them. The function receives the child name and should return the corresponding key name.
  • AValueIndex — If each pair in AKey contains more than one value, set this param to an index >=0 to consider that value. Normally each pair contains a single value, so you just don't pass this param.

Released under Apache License, Version 2.0.