--- source_files: - DataPRO/DbAPI/Groups/IGroupHardware.cs - DataPRO/DbAPI/Groups/IGroups.cs - DataPRO/DbAPI/Groups/GroupHardware.cs - DataPRO/DbAPI/Groups/Groups.cs generated_at: "2026-04-16T04:26:08.555940+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "1e70835e7b48ab2d" --- # GroupHardware and Groups Module Documentation --- ## 1. Purpose This module provides data access layer (DAL) functionality for managing *Groups* and *GroupHardware* entities in the database. It exposes interfaces (`IGroups`, `IGroupHardware`) and their concrete implementations (`Groups`, `GroupHardware`) to perform CRUD operations (Create, Read, Update, Delete) against the `Groups` and `GroupHardware` tables via stored procedures. The module enforces user authentication before executing database operations and centralizes error handling and logging for these operations. It serves as the primary interface for group-based configuration and hardware association logic elsewhere in the system. --- ## 2. Public Interface ### `IGroupHardware` Interface (Namespace: `DbAPI.GroupHardware`) | Method | Signature | Description | |--------|-----------|-------------| | `GroupHardwareInsert` | `ulong GroupHardwareInsert(IUserDbRecord user, IConnectionDetails connection, GroupHardwareDbRecord groupHardware, out int newId, out string errorMessage)` | Inserts a new record into the `GroupHardware` table using `sp_GroupHardwareInsert`. Returns `ERROR_SUCCESS` (0) on success; otherwise returns a non-zero error code. `newId` is the ID of the inserted record. `errorMessage` contains the error text on failure. | | `GroupHardwareGet` | `ulong GroupHardwareGet(IUserDbRecord user, IConnectionDetails connection, int? groupId, string serialNumber, bool? embedded, out GroupHardwareDbRecord[] groupHardwareRecords)` | Retrieves records from `GroupHardware` matching the provided filters (`groupId`, `serialNumber`, `embedded`). Returns `ERROR_SUCCESS` on success. `groupHardwareRecords` contains the result array (possibly empty). | | `GroupHardwareDelete` | `ulong GroupHardwareDelete(IUserDbRecord user, IConnectionDetails connection, int? groupId, int? dasId, out string errorString)` | Deletes a record from `GroupHardware` identified by `groupId` and `dasId` using `sp_GroupHardwareDelete`. Returns `ERROR_SUCCESS` (0) on success; otherwise returns the stored procedure’s error code. `errorString` contains the error message from the stored procedure or exception. | ### `IGroups` Interface (Namespace: `DbAPI.Groups`) | Method | Signature | Description | |--------|-----------|-------------| | `GroupsInsert` | `ulong GroupsInsert(IUserDbRecord user, IConnectionDetails connection, ref IGroupDbRecord group)` | Inserts a new group into the `Groups` table using `sp_GroupsInsert`. On success, `group.Id` is populated with the new record’s ID. Returns `ERROR_SUCCESS` (0) on success; otherwise `ERROR_UNKNOWN`. | | `GroupsUpdate` | `ulong GroupsUpdate(IUserDbRecord user, IConnectionDetails connection, IGroupDbRecord group)` | Updates an existing group in the `Groups` table using `sp_GroupsUpdate`. Returns `ERROR_SUCCESS` (0) on success; otherwise `ERROR_UNKNOWN`. | | `GroupsGet` | `ulong GroupsGet(IUserDbRecord user, IConnectionDetails connection, int? id, string serialNumber, string displayName, bool? embedded, int? staticGroupId, out IGroupDbRecord[] groups)` | Retrieves group records matching the provided filters (`id`, `serialNumber`, `displayName`, `embedded`, `staticGroupId`). Returns `ERROR_SUCCESS` on success. `groups` contains the result array (possibly empty). | | `GroupsDelete` | `ulong GroupsDelete(IUserDbRecord user, IConnectionDetails connection, long id, out string errorString)` | Deletes a group identified by `id` using `sp_GroupsDelete`. Returns `ERROR_SUCCESS` (0) on success; otherwise returns the stored procedure’s error code. `errorString` contains the error message from the stored procedure or exception. | > **Note**: All methods require a logged-in user (`IsUserLoggedIn` check). Failure to authenticate returns `ERROR_ACCESS_DENIED`. --- ## 3. Invariants - **Authentication**: All public methods first verify the user is logged in via `DbAPI.Connections.IsUserLoggedIn(user, connection)`. If not, they return `ERROR_ACCESS_DENIED` without invoking the database. - **Stored Procedure Usage**: All database interactions occur exclusively through stored procedures: - `sp_GroupHardwareInsert`, `sp_GroupHardwareGet`, `sp_GroupHardwareDelete` - `sp_GroupsInsert`, `sp_GroupsUpdate`, `sp_GroupsGet`, `sp_GroupsDelete` - **Error Handling**: - Non-zero `@errorNumber` output parameter from stored procedures indicates failure. - On failure, the error code is returned as a `ulong`, and the `@errorMessage` output parameter is logged and/or propagated. - Exceptions during execution result in `ERROR_UNKNOWN` (value not specified in source, but implied by usage). - **Resource Disposal**: All `SqlCommand` objects and their connections are disposed in `finally` blocks. - **Null Handling**: - `GroupsInsert` treats `ExtraProperties` as empty string if `null`. - `GroupsUpdate` passes `ExtraProperties` directly (including `null`), which may be handled by the stored procedure. - `GroupsGet` and `GroupHardwareGet` accept nullable parameters and pass `null` to the stored procedure if not provided. --- ## 4. Dependencies ### Module Dependencies (Imports/Usings): - **Database Abstraction**: - `DbAPI.Connections` (`IUserDbRecord`, `IConnectionDetails`, `IsUserLoggedIn`, `ConnectionManager`) - `DTS.Common.Interface.Database` (`IUserDbRecord`, `IConnectionDetails`) - `System.Data`, `System.Data.SqlClient` (ADO.NET types: `SqlCommand`, `SqlParameter`, `SqlDbType`, `CommandType`, `SqlDataReader`) - **Group/GroupHardware Models**: - `DTS.Common.Interface.Groups` (`IGroupDbRecord`) - `DTS.Common.Interface.Groups.GroupList` (likely contains `IGroupDbRecord` and `GroupHardwareDbRecord`) - `DTS.Common.Classes.Groups` (`GroupHardwareDbRecord`, `GroupDbRecord`) - **Error & Logging**: - `DbAPI.Errors` (`ErrorCodes`) - `DbAPI.Logging` (`LogManager`, `TraceEventType`, `LogManager.LogEvents`) ### Inferred Usage: - **Consumers**: Likely used by higher-level business logic (e.g., test setup management, group configuration UI/backend services) that need to manage hardware-group associations and group metadata. - **Database Dependencies**: - Requires the following stored procedures to exist in the database: - `sp_GroupHardwareInsert` - `sp_GroupHardwareGet` - `sp_GroupHardwareDelete` - `sp_GroupsInsert` - `sp_GroupsUpdate` - `sp_GroupsGet` - `sp_GroupsDelete` --- ## 5. Gotchas - **Parameter Mismatch in `GroupHardwareDelete`**: The XML doc comment states `groupId` and `dasId` are "Id in the GroupHardware table", but the method signature uses `int? groupId` and `int? dasId`. However, the stored procedure `sp_GroupHardwareDelete` likely expects these as *composite key values* (group ID + DAS ID), not a single primary key. This may be confusing if the table uses a surrogate key (e.g., `GroupHardwareId`). - **Inconsistent Error Code Propagation in `GroupHardwareDelete`**: On stored procedure error, `GroupHardwareDelete` throws an exception (with `errorMessage`) but then catches it and returns `ERROR_UNKNOWN`, losing the original error code. The `errorString` is only partially populated (exception message prepended), and the original error code is discarded. - **`GroupsInsert` Uses `ref` Parameter**: The `group` parameter is `ref`, meaning the method modifies the caller’s object (specifically `group.Id`). This is non-idiomatic in modern C# and could surprise developers unfamiliar with this convention. - **`GroupsUpdate` Does Not Update `Id`**: The `Id` field is used only as input (for the `WHERE` clause), and the method does not modify the `group` object on success. This is expected, but worth noting. - **`GroupsGet` Logs `"GroupsGet failed"` in `GroupHardware` Class**: In `GroupHardware.cs`, the `GroupHardwareGet` method logs `"GroupsGet failed"` on exception — this appears to be a copy-paste error in the log message. - **`ExtraProperties` Handling Inconsistency**: `GroupsInsert` defaults `ExtraProperties` to `""` if `null`, but `GroupsUpdate` passes `null` directly. If the stored procedure or database expects non-null, this could cause issues. - **No Validation on Input Parameters**: No explicit validation (e.g., null checks on `serialNumber`, `displayName`) is performed before calling stored procedures — behavior depends on stored procedure robustness. - **`GroupsDelete` Uses `long id` but Stored Procedure Uses `@Id` as `Int`**: The interface method signature uses `long id`, but the stored procedure parameter is `SqlDbType.Int`. This may cause truncation or runtime errors if `id` exceeds `Int32.MaxValue`.