---
title: Retrieve single preference blob
summary: Read one stored preference payload for an application, user, and optional page scope.
status: draft
owner: SAIF Team
last_reviewed: 2026-07-30
library: SAIF.Framework.Preferences
reference_type: package
operation_id: OP-PREF-001
trigger: Caller invokes PreferenceData.GetPreferences
---

# Retrieve single preference blob

This is the library's simplest read path: it looks up at most one `USER_PREFERENCE` row for a given application name, normalized user ID, and optional page name, and returns the stored `PREFERENCE_TEXT` string when a matching row exists.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-PREF-001 |
| **Trigger** | Caller invokes `PreferenceData.GetPreferences(appName, pageName, userId)`. |
| **Inputs** | `appName`, `pageName`, `userId` |
| **Outputs** | `PREFERENCE_TEXT` as `string`, or `string.Empty` when no row matches |
| **Primary components** | `PreferenceData.GetPreferences`, `SqlHelper.ResultSetQuery`, `clsResultSet.DataRow.GetString` |
| **Entry point** | `SAIF.Framework.Preferences\PreferenceData.cs` |

## Steps

1. Start with the base SELECT text for `USER_ID`, `APP_NAME`, `PAGE_NAME`, and `PREFERENCE_TEXT` from [USER_PREFERENCE](../database-tables.md#user_preference) ([SQL-002](../sql/SQL-002-get-preferences.md)).
2. Reset the parameter list, create a `SqlHelper.ResultSetQuery` bound to the injected `IDataPortalInfo`, and add `:userid` as `userId.ToLower()` plus `:appname` as the requested application name ([BR-001](../business-rules.md#br-001-user-ids-are-normalized-to-lower-case), [SQL-002](../sql/SQL-002-get-preferences.md), [USER_PREFERENCE](../database-tables.md#user_preference)).
3. Apply scope selection for the optional page name ([BR-003](../business-rules.md#br-003-preference-identity-is-scoped-by-app-user-and-optional-page), [SQL-002](../sql/SQL-002-get-preferences.md), [USER_PREFERENCE](../database-tables.md#user_preference)).
   - If `pageName` is empty, append `and PAGE_NAME is NULL`.
   - If `pageName` is present, append `and PAGE_NAME = :pagename` and add the matching bind parameter.
4. Attach the accumulated parameters and execute the result-set query against the active portal ([SQL-002](../sql/SQL-002-get-preferences.md), [USER_PREFERENCE](../database-tables.md#user_preference)).
   - Create the portal request in the `SqlHelper.ResultSetQuery` constructor.
   - Add the bind variables to `DataRequest` through `AddParms`.
   - Set `DataRequest.RequestType` to `ResultSet` and `DataRequest.SQLStatement` to the final SQL text.
   - Call `IDataPortalInfo.ProcessPortalRequest`, then cast `DataRequest.Result` back to `clsResultSet`.

   > **Origin**: Steps 4.1–4.4 are implemented by [Execute a data portal request](../../saif-framework-core/operations/execute-data-portal-request.md) (`SAIF.Framework.Core`) and executed on behalf of this operation.
5. Inspect the returned result set.
   - If `result.Count > 0`, return `result[0].GetString("PREFERENCE_TEXT")` from the first row.
   - If no row is returned, return `string.Empty`.
6. Complete without additional validation or duplicate-row handling.
   - On failure: any portal or data-conversion exception propagates to the caller because this method has no local recovery logic.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Caller invokes GetPreferences]) --> Build[Build scoped SELECT]
	Build --> Execute[Execute result-set query]
	Execute --> Found{Any rows returned?}
	Found -->|Yes| ReturnText([Return first PREFERENCE_TEXT])
	Found -->|No| ReturnEmpty([Return string.Empty])
```

## Failure and edge-case behavior

- Empty `pageName` switches the scope to `PAGE_NAME is NULL` instead of binding `:pagename`.
- Only the first matching row is returned; the method does not check for or report duplicates.
- Failures from portal execution or `GetString` conversion are not handled locally and surface to the caller as-is.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [SQL catalog](../sql/index.md)
- [Database tables](../database-tables.md)

## Sources
- SAIF.Framework.Preferences\PreferenceData.cs
- SAIF.Framework.Core\V1\DataAccessLayer\SqlHelper.vb
- SAIF.Framework.Core\V1\DataAccessLayer\clsResultSet.vb
