Files
DP44/enriched-qwen3-coder-next/DataPRO/Modules/InstallerCustomActions/LocalSQLDB.md
2026-04-17 14:55:32 -04:00

82 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
source_files:
- DataPRO/Modules/InstallerCustomActions/LocalSQLDB/LocalDBPreparation.cs
- DataPRO/Modules/InstallerCustomActions/LocalSQLDB/LocalDBPrepare.cs
generated_at: "2026-04-16T04:44:18.702457+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "53877159cb79be1f"
---
# LocalDB Preparation Module Documentation
## 1. Purpose
This module implements a Windows Installer custom action responsible for preparing a local SQL Server Express LocalDB instance during installation of the DataPRO application. Specifically, it determines whether the installation targets a *local* or *centralized* database configuration, and if local, copies the default database files (`DataPRO.mdf` and `DataPRO.ldf`) from a previously installed version (if available) or from the current installation directory to a new location named according to the configured database name. It ensures the database files are present before the main installation completes, enabling the application to connect to a pre-populated local database.
## 2. Public Interface
### `LocalDBPreparation.Main(string[] args)`
- **Signature**: `static void Main(string[] args)`
- **Behavior**: Entry point for the custom action executable. Parses the first two arguments as `targetDir` (installation directory) and `productVersion` (version of the product being installed). Instantiates `LocalDBPrepare` with these values and invokes `PrepareDB()`. On any exception, displays an error message via `MessageBox.Show` and rethrows an exception to abort the installation.
### `LocalDBPrepare.PrepareDB()`
- **Signature**: `public bool PrepareDB()`
- **Behavior**: Orchestrates the database preparation logic:
1. Reads the new installations configuration file to determine the database type (`DBType`) and database name (`DBName`).
2. If `DBType` is `Centralized`, returns `false` immediately (no local DB preparation needed).
3. If the configured `DBName` matches the default (`Settings.Default.DataPRO`), returns `true` without copying (no rename needed).
4. Otherwise, constructs source and destination paths for `.mdf` and `.ldf` files.
5. Attempts to locate the most recently installed lower version using `Common.PreviousInstall.GetMostRecentlyInstalledSubKeyName` and `GetMostRecentlyInstalledPath`. If no prior version is found, returns `false`.
6. Copies `DataPRO.mdf` and `DataPRO.ldf` from the source path to the destination path (overwriting existing files).
7. Returns `true` upon successful copy.
> **Note**: The method is *not* thread-safe, as it uses static fields (`_targetDir`, `_installingVersion`) to store state.
## 3. Invariants
- **Configuration File Path**: The configuration file is expected at `<targetDir><RegistryDataPROExe>` (e.g., `targetDir + "DataPRO.exe"`), where `RegistryDataPROExe` is a string constant from `Settings.Default`.
- **Database File Naming**: Database files are always named `<DBName>.mdf` and `<DBName>.ldf`, where `DBName` is read from config or defaults to `Settings.Default.DataPRO`.
- **LocalDB Folder**: Database files reside in a subfolder named by `Settings.Default.LocalDbFolder` (e.g., `"LocalDB"`).
- **File Extension Constants**: `.mdf` and `.ldf` extensions are defined in `Settings.Default.Mdf` and `Settings.Default.LogLdf`, respectively.
- **DBType Parsing Fallback**: If `DBType` cannot be parsed from config, it defaults to `DbType.Local`.
- **Copy Source Priority**: If a prior installation exists, source files are taken from the prior installation directory; otherwise, they are taken from the current `targetDir`.
- **Return Value Semantics**:
- `true`: Local DB preparation completed successfully (including no-op case where DB name matches default).
- `false`: Either centralized DB mode, no prior installation found (when renaming is needed), or an early exit condition.
## 4. Dependencies
### External Dependencies (from imports):
- `System.Configuration` (`ConfigurationManager`, `SettingElementCollection`, etc.)
- `System.Data.SqlClient` (imported but *not used* in current code)
- `Microsoft.Win32` (likely for registry access via `Common.PreviousInstall`)
- `System.Security.Principal` (imported but *not used*)
- `System.Windows.Forms` (used only for `MessageBox.Show` in `Main`)
- `System.Threading` (imported but *not used*)
- `LocalSQLDB.Properties.Settings` (strongly-typed settings from `Settings.Designer.cs`)
### Internal Dependencies:
- `Common.PreviousInstall` (static class, not shown in source) — provides:
- `GetMostRecentlyInstalledSubKeyName(Version, out string)`
- `GetMostRecentlyInstalledPath(string subKeyName)`
- `Settings.Default` (strongly-typed settings) — relies on:
- `DataPRO`, `LocalDbFolder`, `Mdf`, `LogLdf`, `RegistryDataPROExe`, `ApplicationSettings`
### What Depends on This Module:
- Windows Installer (via custom action executable `LocalSQLDB.exe`, presumably invoked during install sequence).
- The DataPRO installer project (not shown) — this module is part of the `InstallerCustomActions` folder.
## 5. Gotchas
- **Static State in `LocalDBPrepare`**: Fields `_targetDir` and `_installingVersion` are `static`, meaning if multiple instances of `LocalDBPrepare` are created (e.g., in tests or concurrent invocations), they will share state — a potential source of race conditions or incorrect behavior. The class is instantiated once per run, but the design is fragile.
- **Hardcoded Default DB Name**: Logic assumes `Settings.Default.DataPRO` is the canonical default database name; renaming only occurs if the configured name differs.
- **Uncommented Code Paths**: Several lines of code are commented out (e.g., `//if (_newSettingsDictionary[ConfigSettings.DBCopy.ToString()])`), suggesting incomplete refactoring or legacy behavior. The current logic *always* falls back to copying from `targetDir` if no prior install exists — but the intent is unclear.
- **No Validation of File Existence**: `File.Copy` is called without verifying the source files exist first. If `sourceFileName` points to a non-existent file, a `FileNotFoundException` will be thrown and caught by the top-level `try/catch`, causing installation failure.
- **Exception Handling Obsfuscation**: The top-level `catch` in `Main` rethrows a *new* `Exception()` without preserving the original exception details (e.g., stack trace), making debugging difficult.
- **Enum Parsing Fragility**: `Enum.TryParse` for `DbType` is case-sensitive by default; if the config value is `"local"` (lowercase) but the enum expects `"Local"`, it will fail and default to `DbType.Local`. This may be intentional, but is not documented.
- **No Rollback on Partial Copy**: If copying the `.mdf` succeeds but the `.ldf` fails, the database files will be in an inconsistent state. No cleanup or rollback is attempted.
- **Assumes LocalDB Folder Exists**: The code constructs paths using `Settings.Default.LocalDbFolder` but does not ensure the folder exists before copying files. `File.Copy` will throw if the directory is missing.
- **Missing `using` for `System.IO`**: Though `System.IO.File.Copy` is used, `using System.IO;` is not declared — implying it is implicitly available (e.g., via other `using`s or project-level settings), but this is a potential portability issue.
None identified beyond those above.