--- source_files: - DataPRO/DbAPI/Database/IDatabase.cs - DataPRO/DbAPI/Database/Database.cs generated_at: "2026-04-16T04:24:57.920635+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "460fbd3d82516ff4" --- # Database ## Documentation: `DbAPI.Database` Module --- ### 1. Purpose This module provides core database versioning and metadata operations for the DataPRO system. It defines and implements the `IDatabase` interface, enabling retrieval of the highest database version (`GetDatabaseVersion`), insertion of new version records (`InsertDatabaseVersion`), and extraction of the SQL Server major version (`GetSQLVersion`). It also includes utility methods for resolving versioned stored procedure names (`GetStoredProcedureVersion`, `GetStoredProcedureVersionCached`, `PrepareForDbAccess`), supporting backward/forward compatibility across database schema versions. The module acts as a low-level abstraction layer between application logic and SQL Server, enforcing user authentication and delegating to stored procedures for persistence. --- ### 2. Public Interface The interface `IDatabase` is the public contract. The concrete implementation `Database` is `internal`, so only `IDatabase` members are externally visible. #### `IDatabase.GetSQLVersion(IConnectionDetails connection) → int` - **Behavior**: Retrieves the major version number (e.g., `15` for SQL Server 2019) from the server’s `ServerVersion` string. - **Notes**: Does *not* require user authentication. Returns `0` on failure (e.g., parsing error or connection issue). #### `IDatabase.GetDatabaseVersion(IUserDbRecord user, IConnectionDetails connection, out int version) → ulong` - **Behavior**: Executes the stored procedure `sp_DBVersionGet` to fetch all version records, then returns the maximum version number via the `out int version` parameter. - **Authentication**: Does *not* enforce user login (despite XML comment stating “User must be logged in” — implementation explicitly allows querying without login). - **Return**: `ErrorCodes.ERROR_SUCCESS` (0) on success; `ErrorCodes.ERROR_UNKNOWN` on exception. - **Output**: `version` is set to `0` on failure. #### `IDatabase.InsertDatabaseVersion(IUserDbRecord user, IConnectionDetails connection, int version, int step, DateTime date, string remarks, string userField) → ulong` - **Behavior**: Inserts a new version record into the database by calling the stored procedure `sp_DbVersionInsert`. - **Authentication**: Explicitly checks `IsUserLoggedIn(user, connection)`; returns `ErrorCodes.ERROR_ACCESS_DENIED` if not logged in. - **Parameters**: - `version`, `step`, `date`, `remarks`, `userField` → values inserted into the record. - **Return**: `ErrorCodes.ERROR_SUCCESS` on success; `ErrorCodes.ERROR_UNKNOWN` on SQL error (non-zero `@errorNumber` output) or exception. - **Notes**: Does *not* validate uniqueness or ordering of version numbers — duplicates or regressions are allowed. #### `Database.GetStoredProcedureVersion(IConnectionDetails connection, string storedProcedure, int clientDbVersion) → string` - **Behavior**: Resolves the correct stored procedure name (e.g., `sp_MyProc` vs `sp_MyProc_3`) based on client and DB versions. Calls `DbAPI.GetStoredProcedureToUse`. - **Fallback**: Returns original `storedProcedure` name if resolution fails. #### `Database.GetStoredProcedureVersionCached(IConnectionDetails connection, string storedProcedure) → string` - **Behavior**: Same as `GetStoredProcedureVersion`, but uses a cached result (via `DbAPI.GetStoredProcedureToUseCached`) to avoid repeated DB lookups. - **Uses**: `connection.ClientDbVersion` as the client version. #### `Database.PrepareForDbAccess(IUserDbRecord user, IConnectionDetails connection, int clientDbVersion, string storedProcedure, out int storedProcedureVersionToUse, out SqlCommand cmd) → ulong` - **Behavior**: A helper to prepare a `SqlCommand` for a versioned stored procedure. - **Steps**: 1. Checks user login (`IsUserLoggedIn`) → returns `ERROR_ACCESS_DENIED` if false. 2. Resolves stored procedure name version via `DbAPI.GetStoredProcedureToUse`. 3. Creates `SqlCommand` via `ConnectionManager.GetSqlCommand`. - **Output**: - `storedProcedureVersionToUse`: resolved version suffix (e.g., `3`), or `0` if none. - `cmd`: fully configured `SqlCommand` object. - **Return**: `ERROR_SUCCESS` on success; otherwise error code (e.g., `ERROR_ACCESS_DENIED`, `ERROR_UNKNOWN`). --- ### 3. Invariants - **Authentication Enforcement**: `InsertDatabaseVersion` and `PrepareForDbAccess` *require* the user to be logged in (checked via `IsUserLoggedIn`). Failure to meet this yields `ERROR_ACCESS_DENIED`. - **Stored Procedure Naming**: Versioned stored procedures follow the pattern `{baseName}_{version}` (e.g., `sp_MyProc_2`). A version suffix of `0` implies no suffix (i.e., base name only). - **Error Handling**: All methods log exceptions to `LogManager` at `TraceEventType.Error` level before returning `ERROR_UNKNOWN`. - **Resource Management**: All `SqlCommand` objects created via `ConnectionManager.GetSqlCommand` have their `.Connection` disposed in `finally` blocks. - **No Validation on Version Values**: `InsertDatabaseVersion` does *not* check for duplicate versions, ordering (e.g., regression), or consistency with existing records. --- ### 4. Dependencies #### Imports/References: - `DbAPI.Connections` → Provides `ConnectionManager`, `IsUserLoggedIn`, and `GetStoredProcedureToUse`/`GetStoredProcedureToUseCached`. - `DbAPI.Errors` → Defines `ErrorCodes` (e.g., `ERROR_SUCCESS`, `ERROR_ACCESS_DENIED`, `ERROR_UNKNOWN`). - `DbAPI.Logging` → `LogManager` for error logging. - `DTS.Common.Interface.Database` → Interfaces `IUserDbRecord`, `IConnectionDetails`. - `DTS.Common.Classes` → Likely contains `Utility.GetInt` (used in `GetDatabaseVersion`). - `System.Data`, `System.Data.SqlClient` → Core ADO.NET types (`SqlCommand`, `SqlParameter`, `SqlDbType`, `CommandType`, `DBNull`, `IDataReader`). #### Used By: - Any module requiring database versioning operations (e.g., upgrade scripts, version reporting, audit logging). - Likely consumed via `IDatabase` interface (injected or resolved via DI/container — not evident from source). --- ### 5. Gotchas - **Contradictory Authentication Requirement**: `GetDatabaseVersion`’s XML comment states *“User must be logged into database”*, but the implementation does **not** call `IsUserLoggedIn`. This is a discrepancy between documentation and behavior. - **No Version Uniqueness/Ordering Checks**: `InsertDatabaseVersion` blindly inserts records — callers must ensure version numbers are monotonically increasing and unique, or risk data inconsistency. - **`GetSQLVersion` Fragility**: Assumes `ServerVersion` is dot-separated (e.g., `"15.0.2000.5"`). Parsing relies on `Split(".")` and `int.Parse` on the first segment — will throw if format changes (e.g., `"15-0-2000"` or `"15.0.2000.5-SP2"`). - **`GetDatabaseVersion` Uses `Max()` on `List`**: If no version records exist, `dbVersionsList.Max()` throws `InvalidOperationException`. However, the `catch` block suppresses this and returns `ERROR_UNKNOWN` with `version = 0`. This is safe but may mask empty-db scenarios. - **Stored Procedure Name Resolution**: `GetStoredProcedureVersion` and `PrepareForDbAccess` rely on external `DbAPI.GetStoredProcedureToUse`/`GetStoredProcedureToUseCached`. Behavior of these (e.g., how version mapping is determined) is not visible here. - **`userField` Parameter Misleading Name**: The `userField` parameter in `InsertDatabaseVersion` is documented as *“What user to associate with the insert record (does not have to match any actual users)”* — implying it’s a free-text field, not a foreign key. Do not assume it validates against a user table. - **No Transaction Support**: All operations are standalone; no mechanism for atomic multi-step versioning (e.g., insert + update). - **`GetStoredProcedureVersionCached` Uses `connection.ClientDbVersion`**: Assumes `IConnectionDetails` exposes a `ClientDbVersion` property — not visible in this module but required for correct behavior. --- *Documentation generated from provided source files. No external behavior or APIs inferred beyond what is explicitly present.*