Files
DP44/enriched-qwen3-coder-next/DataPRO/DbAPI/Channels.md
2026-04-17 14:55:32 -04:00

125 lines
10 KiB
Markdown

---
source_files:
- DataPRO/DbAPI/Channels/IChannels.cs
- DataPRO/DbAPI/Channels/Channels.cs
generated_at: "2026-04-16T04:27:22.495313+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "0eeac4044bafa708"
---
# Documentation: `DbAPI.Channels.IChannels` / `Channels`
## 1. Purpose
This module provides database access layer (DAL) functionality for managing channel-related data in the system, including channel definitions (`Channels` table), channel codes (e.g., ISO codes, user codes), channel settings (both global and group-specific), and channel code types. It serves as the primary interface for CRUD operations on channel data, enforcing authentication, validating parameters, and translating between .NET objects and SQL Server stored procedures. The module is part of the `DbAPI` namespace and is intended for internal use by higher-level components that need to persist or retrieve channel configuration data.
## 2. Public Interface
All methods are defined in the `IChannels` interface and implemented by the internal class `Channels`. Return values are `ulong`, where `0` (`ERROR_SUCCESS`) indicates success and non-zero values indicate error codes (e.g., from `ErrorCodes`).
### Channel Codes
- **`ulong ChannelCodesInsert(IUserDbRecord user, IConnectionDetails connection, IReadOnlyDictionary<ChannelEnumsAndConstants.ChannelCodeType, short> lookup, IChannelCode channelCode, out int id)`**
Inserts a new channel code record. On success, `id` is populated with the new database ID. Requires `channelCode.Code` and `channelCode.Name` to be non-null/non-empty.
- **`ulong ChannelCodesUpdate(IUserDbRecord user, IConnectionDetails connection, IReadOnlyDictionary<ChannelEnumsAndConstants.ChannelCodeType, short> lookup, IChannelCode channelCode)`**
Updates an existing channel code record. Requires `channelCode.Id`, `Code`, and `Name` to be non-null/non-empty.
- **`ulong ChannelCodesDelete(IUserDbRecord user, IConnectionDetails connection, int? id, string code, string name, int? codeType)`**
Deletes channel code records matching any combination of `id`, `code`, `name`, or `codeType`. All parameters are optional; null means “match all”.
- **`ulong ChannelCodeTypesGet(IUserDbRecord user, IConnectionDetails connection, short? id, string codeType, out Tuple<short, string>[] records)`**
Retrieves channel code type definitions (ID and string name). Parameters are filters; null means “match all”.
- **`ulong ChannelCodesGet(IUserDbRecord user, IConnectionDetails connection, int? Id, string code, string name, ChannelEnumsAndConstants.ChannelCodeType? codeType, IReadOnlyDictionary<short, string> channelTypeLookup, out IChannelCode[] records)`**
Retrieves channel code records matching filters. `channelTypeLookup` is required (cannot be null) and maps code type IDs to names for deserialization.
### Channel Settings
- **`ulong ChannelSettingsUpdate(IUserDbRecord user, IConnectionDetails connection, int settingId, string defaultValue)`**
Updates the `DefaultValue` of a channel setting (by `settingId`).
- **`ulong ChannelSettingsGet(IUserDbRecord user, IConnectionDetails connection, int? settingId, string settingName, out IChannelSettingRecord[] records)`**
Retrieves channel settings matching `settingId` and/or `settingName`. Parameters are optional.
- **`ulong GroupChannelSettingsDelete(IUserDbRecord user, IConnectionDetails connection, long channelId, int? settingId)`**
Deletes group channel settings for a given `channelId`. If `settingId` is null, deletes *all* settings for the channel.
- **`ulong GroupChannelSettingsInsert(IUserDbRecord user, IConnectionDetails connection, int clientDbVersion, long channelId, IGroupChannelSettingRecord record)`**
Inserts a new group channel setting. Uses version-aware stored procedure resolution via `Database.Database.PrepareForDbAccess`.
- **`ulong GroupChannelSettingsGet(IUserDbRecord user, IConnectionDetails connection, int clientDbVersion, List<long> channelIdList, out IGroupChannelSettingRecord[] records, out string[] errors)`**
Retrieves group channel settings for a list of channel IDs. Behavior differs based on `clientDbVersion`:
- If `< Constants.BULK_GROUPCHANNELSETTINGS_GET_DB_VERSION`: calls `sp_GroupChannelSettingsGet` repeatedly (one per channel).
- Otherwise: calls a bulk version using a table-valued parameter (`dbo.StringList`).
`errors` is always initialized to an empty array (no errors are populated in current implementation).
### Channels (Main Table)
- **`ulong ChannelsInsert(IUserDbRecord user, IConnectionDetails connection, ref IChannelDbRecord channel)`**
Inserts a new channel record. On success, `channel.Id` is updated with the new database ID. Nullable fields (`DASId`, `SensorId`) are handled conditionally (only added to command if > 0). `IsoCode`, `IsoChannelName`, `UserCode`, `UserChannelName` default to `""` if null.
- **`ulong ChannelsUpdate(IUserDbRecord user, IConnectionDetails connection, IChannelDbRecord channel)`**
Updates an existing channel record. Requires `channel.Id`.
- **`ulong ChannelsGet(IUserDbRecord user, IConnectionDetails connection, int clientDbVersion, long? channelId, int? groupId, int? dasId, int? sensorId, int? testSetupId, string testSetupName, out IChannelDbRecord[] channels)`**
Retrieves channel records matching filters. **Gotcha**: Filters out channels whose `UserChannelName` ends with `DFConstantsAndEnums.USER_CHANNEL_NAME_HUMIDITY` (see *Gotchas*).
- **`ulong ChannelsDelete(IUserDbRecord user, IConnectionDetails connection, long id, out string errorString)`**
Deletes a channel by `id`. Returns error code and populates `errorString` (from stored procedure or exception) on failure.
## 3. Invariants
- **Authentication**: All methods require the user to be logged in (`IsUserLoggedIn(user, connection)`). Returns `ERROR_ACCESS_DENIED` otherwise.
- **Parameter Validation**:
- `ChannelCodesInsert`/`ChannelCodesUpdate`: `channelCode.Code` and `channelCode.Name` must be non-null/non-empty.
- `ChannelCodesGet`: `channelTypeLookup` must be non-null.
- `ChannelsInsert`: `channel.Id` is output-only; input `Id` is ignored (but `GroupId`, `DASId`, `DASChannelIndex`, etc., must be set appropriately).
- **Null Handling**:
- Optional filter parameters (e.g., `id`, `code`, `name`, `codeType`) are passed as SQL `NULL` if null.
- Nullable DB columns (`DASId`, `SensorId`) are omitted from command parameters if ≤ 0.
- **Error Reporting**:
- Stored procedures return `@errorNumber` and `@errorMessage`. Non-zero `@errorNumber``ERROR_UNKNOWN`.
- Exceptions during execution are logged and return `ERROR_UNKNOWN`.
- **Resource Cleanup**: All methods dispose `SqlCommand` and connection in `finally` blocks.
## 4. Dependencies
### Imports/Usings (from source)
- **Core**: `System`, `System.Data`, `System.Data.SqlClient`, `System.Diagnostics`
- **DbAPI**: `DbAPI.Connections`, `DbAPI.Errors`, `DbAPI.Logging`
- **Common Types**:
- `DTS.Common.Interface.Database` (`IUserDbRecord`, `IConnectionDetails`)
- `DTS.Common.Interface.Channels` (`IChannelCode`, `IChannelSettingRecord`, `IGroupChannelSettingRecord`, `IChannelDbRecord`)
- `DTS.Common.Classes.Channels`, `DTS.Common.Classes.ChannelCodes`, `DTS.Common.Classes.Groups.ChannelSettings`
- `DTS.Common.Enums.Channels` (`ChannelEnumsAndConstants`, `ChannelCodeType`)
- `DTS.Common` (`Constants`, `Utility`, `DFConstantsAndEnums`)
### Inferred Dependencies
- **Database**:
- Stored procedures: `sp_ChannelCodesInsert`, `sp_ChannelCodesUpdate`, `sp_ChannelCodesDelete`, `sp_ChannelCodeTypeGet`, `sp_ChannelCodesGet`, `sp_ChannelSettingsUpdate`, `sp_ChannelSettingsGet`, `sp_GroupChannelSettingsDelete`, `sp_GroupChannelSettingsInsert`, `sp_GroupChannelSettingsGet`, `sp_ChannelsInsert`, `sp_ChannelsUpdate`, `sp_ChannelsGet`, `sp_ChannelsDelete`.
- User-defined table type: `dbo.StringList` (used in `GroupChannelSettingsGet`).
- **Other Modules**:
- `ConnectionManager` (for `GetSqlCommand`)
- `Database.Database` (for `GetStoredProcedureVersionCached`, `PrepareForDbAccess`)
- `LogManager` (for logging)
- `ErrorCodes` (for return values)
- `Utility` (for `GetShort`, `GetString`)
- `DFConstantsAndEnums` (for `USER_CHANNEL_NAME_HUMIDITY` constant)
### Implemented By
- `Channels` (internal class in same namespace)
## 5. Gotchas
- **`ChannelsGet` filters out humidity channels**: The implementation explicitly skips records where `UserChannelName.EndsWith(DFConstantsAndEnums.USER_CHANNEL_NAME_HUMIDITY)`. This is hardcoded (comment references case #33192). Consumers cannot override this behavior.
- **`GroupChannelSettingsGet` uses two different stored procedures**: Behavior changes based on `clientDbVersion` relative to `Constants.BULK_GROUPCHANNELSETTINGS_GET_DB_VERSION`. The older version loops over channels and reuses the same `SqlCommand` (parameters cleared between iterations), while the newer uses a table-valued parameter. This implies version compatibility must be handled by callers.
- **`ChannelsInsert` mutates input**: The `channel` parameter is `ref`, and `channel.Id` is updated with the new database ID on success. Callers must pass a mutable instance.
- **Nullable DB columns handled inconsistently**:
- In `ChannelsInsert`, `DASId`/`SensorId` are only added to the command if `> 0`.
- In `ChannelsUpdate`, `DASId` is only added if `> 0`, but `DASChannelIndex` is *always* added (even if `0`).
This may cause issues if `0` is a valid value for `DASChannelIndex` but not for `DASId`.
- **`ChannelSettingsUpdate` uses `ExecuteReader()` instead of `ExecuteNonQuery()`**: Despite updating a setting (not returning rows), it calls `ExecuteReader()` and then discards the reader. This is unusual and may be legacy behavior.
- **`ChannelCodesInsert` logs to wrong event**: Error logs use `LogManager.LogEvents.TestSetups` instead of a channel-specific event. Likely copy-paste error.
- **No validation on `channelCode.CodeType`**: The `lookup` dictionary is accessed directly (`lookup[channelCode.CodeType]`) without checking if the key exists. Will throw `KeyNotFoundException` if `channelCode.CodeType` is not in `lookup`.