Files
2026-04-17 14:55:32 -04:00

7.1 KiB
Raw Permalink Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
DataPRO/Modules/InstallerCustomActions/LocalSQLDB/LocalDBPreparation.cs
DataPRO/Modules/InstallerCustomActions/LocalSQLDB/LocalDBPrepare.cs
2026-04-16T04:44:18.702457+00:00 Qwen/Qwen3-Coder-Next-FP8 1 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 usings or project-level settings), but this is a potential portability issue.

None identified beyond those above.