---
title: Insert preference row
summary: Insert a new USER_PREFERENCE row with sequence-generated identity, normalized user ID, and trimmed payload text.
status: draft
owner: SAIF Team
last_reviewed: 2026-07-30
library: SAIF.Framework.Preferences
reference_type: package
operation_id: OP-PREF-004
trigger: SavePreferences calls PreferenceData.InsertPref after DoesPrefExist returns false
---

# Insert preference row

This internal write operation creates a new `USER_PREFERENCE` row. It binds every column value explicitly, relies on an inline Oracle sequence expression for identity generation, and records audit data from the current portal context.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-PREF-004 |
| **Trigger** | `SavePreferences` calls `InsertPref(appName, pageName, userId, preferenceText)` after `DoesPrefExist` returns `false`. |
| **Inputs** | `appName`, `pageName`, `userId`, `preferenceText` |
| **Outputs** | `true` after the insert request is issued |
| **Primary components** | `PreferenceData.InsertPref`, `SqlHelper.ScalarQuery<int>`, `SqlHelper.NewParm` |
| **Entry point** | `SAIF.Framework.Preferences\PreferenceData.cs` |

## Steps

1. Use the fixed INSERT statement that targets [USER_PREFERENCE](../database-tables.md#user_preference) and embeds the sequence expression [SQL-001](../sql/SQL-001-insert-preference-sequence.md) inside the row-creation command [SQL-004](../sql/SQL-004-insert-preference.md).
2. Create a `SqlHelper.ScalarQuery<int>` bound to the injected `IDataPortalInfo`, reset the parameter list, and bind the row values ([BR-001](../business-rules.md#br-001-user-ids-are-normalized-to-lower-case), [BR-003](../business-rules.md#br-003-preference-identity-is-scoped-by-app-user-and-optional-page), [BR-005](../business-rules.md#br-005-preference-text-is-trimmed-before-storage), [SQL-004](../sql/SQL-004-insert-preference.md), [USER_PREFERENCE](../database-tables.md#user_preference)).
   - Bind `:userid` as `userId.ToLower()`.
   - Bind `:appname` and `:pagename` from the caller inputs.
   - Bind `:prefs` as `preferenceText.Trim()`.
   - Bind `:updated` as `System.DateTime.Now`.
   - Bind `:updateby` as `DPI.UserID`.
3. Attach the parameters and execute the scalar request through the active data portal ([SQL-001](../sql/SQL-001-insert-preference-sequence.md), [SQL-004](../sql/SQL-004-insert-preference.md), [USER_PREFERENCE](../database-tables.md#user_preference)).
   - Create the portal request in the `SqlHelper.ScalarQuery<int>` constructor.
   - Add the bind variables to `DataRequest` through `AddParms`.
   - Set `DataRequest.RequestType` to `Scalar` and `DataRequest.SQLStatement` to the INSERT text.
   - Call `IDataPortalInfo.ProcessPortalRequest`, then cast `DataRequest.Result` to `int` if a scalar result is returned.

   > **Origin**: Steps 3.1–3.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.
4. Discard the scalar result and return `true` after the request completes.
   - On failure: any portal or data-provider exception propagates because this method has no local retry or recovery logic.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([InsertPref called]) --> Build[Build insert parameters]
	Build --> Execute[Execute INSERT with sequence nextval]
	Execute --> EndOk([Return true])
```

## Failure and edge-case behavior

- `pageName` is always bound on insert, even though the read/update/delete paths conditionally append page predicates instead of always binding one.
- The method does not inspect the returned scalar or affected-row count before returning `true`.
- Portal or data-provider failures propagate to the caller unmodified.

## 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
