---
title: Delete preference row
summary: Delete the scoped USER_PREFERENCE row selected by application name, normalized user ID, and optional page name.
status: draft
owner: SAIF Team
last_reviewed: 2026-07-30
library: SAIF.Framework.Preferences
reference_type: package
operation_id: OP-PREF-006
trigger: SavePreferences calls PreferenceData.DeletePref for blank preference text
---

# Delete preference row

This internal write operation removes the preference row that matches the requested application/user scope, applying the same optional page-name scoping used by the read and existence-check paths.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-PREF-006 |
| **Trigger** | `SavePreferences` calls `DeletePref(appName, pageName, userId, preferenceText)` when the trimmed preference text is empty. |
| **Inputs** | `appName`, `pageName`, `userId`, `preferenceText` |
| **Outputs** | `true` after the delete request is issued |
| **Primary components** | `PreferenceData.DeletePref`, `SqlHelper.ScalarQuery<int>` |
| **Entry point** | `SAIF.Framework.Preferences\PreferenceData.cs` |

## Steps

1. Start with the base DELETE statement for [USER_PREFERENCE](../database-tables.md#user_preference) filtered by `USER_ID` and `APP_NAME` ([SQL-006](../sql/SQL-006-delete-preference.md), [USER_PREFERENCE](../database-tables.md#user_preference)).
2. Create a `SqlHelper.ScalarQuery<int>`, reset the parameter list, and bind `:userid` as `userId.ToLower()` plus `:appname` as the application name ([BR-001](../business-rules.md#br-001-user-ids-are-normalized-to-lower-case), [SQL-006](../sql/SQL-006-delete-preference.md), [USER_PREFERENCE](../database-tables.md#user_preference)).
3. Apply optional page scoping before execution ([BR-003](../business-rules.md#br-003-preference-identity-is-scoped-by-app-user-and-optional-page), [SQL-006](../sql/SQL-006-delete-preference.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 bind the page parameter.
4. Attach the parameters and execute the delete request through the active portal ([SQL-006](../sql/SQL-006-delete-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 DELETE text.
   - Call `IDataPortalInfo.ProcessPortalRequest`, then cast `DataRequest.Result` to `int` if a scalar result is returned.

   > **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. Return `true` without checking how many rows were actually removed.
   - On failure: any portal or provider exception propagates to the caller.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([DeletePref called]) --> Scope[Apply page-specific delete scope]
	Scope --> Execute[Execute DELETE]
	Execute --> EndOk([Return true])
```

## Failure and edge-case behavior

- Empty `pageName` scopes the delete to rows whose `PAGE_NAME` is `NULL`.
- A request that matches zero rows still returns `true`, so callers cannot distinguish "deleted" from "nothing to delete".
- The `preferenceText` parameter is accepted but unused; it has no effect on delete behavior.

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