--- 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 installation’s 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 `` (e.g., `targetDir + "DataPRO.exe"`), where `RegistryDataPROExe` is a string constant from `Settings.Default`. - **Database File Naming**: Database files are always named `.mdf` and `.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.