SAIF.Framework.Preferences business rules
This page captures business rules enforced by SAIF.Framework.Preferences when reading, writing, and normalizing preference data in USER_PREFERENCE .
BR-001: User IDs are normalized to lower case
Field
Value
Statement
User IDs are normalized to lower case before querying or storing preference data.
Trigger
Any call to GetPreferences, GetPreferencesForUser, InsertPref, UpdatePref, DeletePref, or DoesPrefExist.
Enforcement
userId.ToLower() is passed to SqlHelper.NewParm("userid", ...) in each method.
Outcome
Preference lookups and writes are effectively case-insensitive on user ID.
Tables
USER_PREFERENCE
SQL
SQL-002 , SQL-003 , SQL-004 , SQL-005 , SQL-006 , SQL-007
Source
SAIF.Framework.Preferences\PreferenceData.cs
BR-002: Empty preference text triggers deletion
Field
Value
Statement
Saving an empty or whitespace-only preference value deletes the existing row rather than storing an empty value.
Trigger
SavePreferences is called with preferenceText that is empty or whitespace-only after Trim().
Enforcement
SavePreferences branches to the DeletePref path.
Outcome
The preference row for that app/page/user is removed instead of persisting an empty value.
Tables
USER_PREFERENCE
SQL
SQL-006
Source
SAIF.Framework.Preferences\PreferenceData.cs
BR-003: Preference identity is scoped by app, user, and optional page
Field
Value
Statement
A preference is uniquely identified by application name, user ID, and an optional page name; a preference with no page name is distinct from one scoped to a specific page.
Trigger
Any read, write, or delete operation against USER_PREFERENCE.
Enforcement
The whereNull (PAGE_NAME IS NULL) and wherePageName (PAGE_NAME = :pagename) constant clauses are applied consistently across GetPreferences, UpdatePref, DeletePref, and DoesPrefExist.
Outcome
Application/user/page-scoped preferences do not collide with application/user-only preferences.
Tables
USER_PREFERENCE
SQL
SQL-002 , SQL-004 , SQL-005 , SQL-006 , SQL-007
Source
SAIF.Framework.Preferences\PreferenceData.cs
BR-004: Update is skipped when stored value is unchanged
Field
Value
Statement
An update is a no-op when the new preference text is identical to the currently stored value.
Trigger
UpdatePref executes as part of SavePreferences.
Enforcement
The PREFERENCE_TEXT <> :prefs condition in the UPDATE ... WHERE clause.
Outcome
Redundant writes and audit-timestamp churn are avoided when the new value equals the existing value.
Tables
USER_PREFERENCE
SQL
SQL-005
Source
SAIF.Framework.Preferences\PreferenceData.cs
BR-005: Preference text is trimmed before storage
Field
Value
Statement
Preference text is trimmed of leading/trailing whitespace before it is persisted.
Trigger
InsertPref or UpdatePref executes.
Enforcement
preferenceText.Trim() is passed as the prefs parameter.
Outcome
Leading/trailing whitespace is never persisted in PREFERENCE_TEXT.
Tables
USER_PREFERENCE
SQL
SQL-004 , SQL-005
Source
SAIF.Framework.Preferences\PreferenceData.cs
BR-006: Preference item payload is JSON-encoded key/value data
Field
Value
Statement
The PREFERENCE_TEXT column stores a JSON-encoded key/value dictionary, deserialized on read into Preference.PreferenceItems.
Trigger
GetPreferencesForUser deserializes PREFERENCE_TEXT for each returned row.
Enforcement
serializer.Deserialize<Dictionary<string, string>>(json) is invoked only when the trimmed JSON text has non-zero length.
Outcome
Preference.PreferenceItems reflects the stored key/value pairs; empty stored text yields an empty dictionary.
Tables
USER_PREFERENCE
SQL
SQL-003
Source
SAIF.Framework.Preferences\PreferenceData.cs
Notes
All six rules above are enforced entirely within PreferenceData; there is no separate IBusinessCriteria/business-object rule layer in this library.
No security, authorization, or segregation-of-duties rules were found in this library; userId is used purely as a data key, not as an authorization decision point.
Sources
SAIF.Framework.Preferences\PreferenceData.cs
SAIF.Framework.Preferences\Preference.cs