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

12 KiB
Raw Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
DataPRO/Modules/Database/DatabaseServices/ViewModel/DatabaseStatusBarViewModel.cs
DataPRO/Modules/Database/DatabaseServices/ViewModel/DatabaseSwitchViewModel.cs
DataPRO/Modules/Database/DatabaseServices/ViewModel/DatabaseCopyViewModel.cs
2026-04-16T04:35:56.029845+00:00 Qwen/Qwen3-Coder-Next-FP8 1 f187d4b018ffae25

Database Services ViewModels Documentation

1. Purpose

This module provides UI-facing view models (DatabaseStatusBarViewModel, DatabaseSwitchViewModel, and DatabaseCopyViewModel) that manage database connection state, user interaction for database switching/copying, and status reporting in the DataPRO application. These view models coordinate database operations (local vs. remote), handle UI state (busy indicators, progress bars, notifications), and integrate with Prisms event aggregation and Unity DI container for decoupled communication with other system components. They serve as the bridge between low-level database operations (e.g., DbOperations, DatabaseServices) and the WPF UI layer.


2. Public Interface

DatabaseStatusBarViewModel

  • string ActiveDbName { get; }
    Returns a string representing the active database: "Local" for DbType.LocalOnly, ServerName for DbType.RemoteOnly, or ServerName/"Local" conditionally for DbType.RemoteLocalHybrid.

  • Brush BackgroundBrush { get; }
    Returns Brushes.Red when DatabaseType == DbType.RemoteLocalHybrid and RemoteConnected == false; otherwise Brushes.Transparent.

  • bool RemoteConnected { get; }
    Returns the value of DbOperations._usingCentralizedDB.

  • string ServerName { get; private set; }
    Holds the remote server name; updated via InitializeValues or OnDbEvent.

  • void InitializeValues(DbType dbType, string serverName, bool remoteConnected)
    Sets DatabaseType, ServerName, and triggers property change notifications for ActiveDbName and BackgroundBrush.

  • void OnDbEvent(DbStatusArg args)
    Internal event handler for DbStatusEvent; updates ServerName and notifies changes to ActiveDbName/BackgroundBrush when args.Status == LegacyStatus.

  • bool IsBusy { get; set; }
    Binds to UI busy indicator; updated via OnBusyIndicatorNotification.

  • bool IsMenuIncluded, bool IsNavigationIncluded
    UI state flags for menu/navigation visibility; support INotifyPropertyChanged.

  • InteractionRequest<Notification> NotificationRequest { get; }
    Prism interaction request used to show notification popups.

  • InteractionRequest<Confirmation> ConfirmationRequest { get; }
    Prism interaction request used to show confirmation dialogs.

  • IDatabaseStatusBarView View { get; set; }
    Reference to the associated view; View.DataContext is set to this in constructor.

  • Constructors

    • DatabaseStatusBarViewModel(IDatabaseStatusBarView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)
      Registers event subscriptions for RaiseNotification, BusyIndicatorChangeNotification, and DbStatusEvent.
    • DatabaseStatusBarViewModel()
      Parameterless constructor (used for design-time or manual instantiation).
  • Lifecycle methods (no-op)
    Unset(), Cleanup(), CleanupAsync(), Initialize(), Initialize(object), Initialize(object, object), InitializeAsync(), InitializeAsync(object), Activated() — all currently empty.

DatabaseSwitchViewModel

  • bool RemoteIsActive { get; }
    Returns DbOperations._usingCentralizedDB.

  • void SwitchRemote()
    Attempts to switch to remote database:

    1. Publishes AppStatusArg.Busy.
    2. Calls DatabaseServices.SetupForRemoteDb(...) with stored credentials.
    3. Validates connection via SimpleDbTest().
    4. On failure: publishes DbStatusEvent with FailedToConnectToRemote, calls SwitchLocal(), logs exception.
    5. On success: publishes DbStatusEvent.LegacyStatus, AppStatusArg.Available, and LogoutUserEvent (reason: DatabaseSwitch).
  • void SwitchLocal()
    Switches to local database:

    1. Checks local DB files exist via CheckLocalDatabaseFilesExist(...).
    2. Publishes AppStatusArg.Busy.
    3. Calls DatabaseServices.SetupLocal(...).
    4. Publishes DbStatusEvent.LegacyStatus, AppStatusArg.Available, and LogoutUserEvent.
  • void InitializeDbSettings(string defaultDbName, string dbHost, bool ntlmAuthentication, string dbUser, string dbPassword)
    Stores connection settings for later use in SwitchRemote().

  • Properties: DefaultDbName, DbHost, NTLMAuthentication, DbUser, DbPassword (all private set).

  • bool IsBusy, IsMenuIncluded, IsNavigationIncluded
    Same semantics as DatabaseStatusBarViewModel.

  • Constructors & Lifecycle methods
    Same as DatabaseStatusBarViewModel; constructor subscribes to RaiseNotification and BusyIndicatorChangeNotification.

DatabaseCopyViewModel

  • bool CopyEnabled { get; }
    Returns true only if DatabaseType == DbType.RemoteLocalHybrid and DbOperations._usingCentralizedDB == true.

  • void CopyDatabase()
    Triggers CopyFunc() on a background task (Task.Run). Publishes AppStatusArg.Busy before and AppStatusArg.Available after.

  • void InitializeState(DbType dbType, string dbName)
    Sets DatabaseType and DbName, publishes initial ProgressBarEvent for both progress bars (collapsed), and notifies CopyEnabled.

  • string DbName { get; private set; }
    Name of the database being copied.

  • bool IsCopyVisible { get; set; }
    Controls visibility of the copy UI section.

  • IStatusAndProgressBarView OverallProgressBarView, IStatusAndProgressBarView CurrentTaskProgressBarView
    References to progress bar views resolved during InitializeAsync().

  • Task InitializeAsync()
    Resolves and configures two IStatusAndProgressBarView instances:

    • One for OverallTaskBar (named "OverallStatus").
    • One for CurrentTaskBar (named "CurrentTaskStatus").
      Each is bound to a shared IStatusAndProgressBarViewModel instance.
  • void OnRaiseNotification(NotificationContentEventArgs)
    Wraps event args into Notification and raises NotificationRequest.

  • void OnBusyIndicatorNotification(bool)
    Sets IsBusy.

  • bool IsBusy, IsMenuIncluded, IsNavigationIncluded, IsDirty
    Same semantics as above.

  • Internal helper methods (private)

    • CopyFunc(): Main copy logic:
      1. Backs up local DB.
      2. Disables constraints.
      3. Copies all tables in _allDBTables via CopyRemoteTable(...).
      4. Fixes Channels.DASId = 0 → NULL.
      5. Re-enables constraints.
      6. Restores local DB on failure.
      7. Publishes progress via ProgressBarEvent.
    • CopyRemoteTable(string tableName, bool bIndentityTable): Fetches all rows from remote DB, stores in memory.
    • InsertIntoLocalTable(...): Inserts rows in batches (max 20 rows/batch to avoid SQL parameter limit), handles IDENTITY_INSERT for tables in _tablesWithIdentities.
    • SetStatus(string bar, double percentage, string text): Publishes ProgressBarEvent.
  • Constants & Data

    • MAX_BATCH_SIZE = 20
    • _allDBTables: List of 72 table names (includes duplicates like "tblDataPRODbVersion" and "DataPRODbVersion").
    • _tablesWithIdentities: HashSet of 58 table names requiring IDENTITY_INSERT ON/OFF.

3. Invariants

  • RemoteConnected is derived solely from DbOperations._usingCentralizedDB — no local state overrides it.
  • ActiveDbName and BackgroundBrush depend on DatabaseType and RemoteConnected — their values are recalculated only when DatabaseType or ServerName changes (via InitializeValues or OnDbEvent).
  • Progress bars are always reset to collapsed/zero on completion/failureCopyFunc() publishes ProgressBarEvent with Visibility.Collapsed in finally.
  • CopyDatabase() runs asynchronouslyTask.Run is used explicitly; no async/await is used internally.
  • DatabaseCopyViewModel requires InitializeAsync() to be called before CopyDatabase() — otherwise OverallProgressBarView/CurrentTaskProgressBarView remain null.
  • DatabaseSwitchViewModel.SwitchRemote() and SwitchLocal() always trigger LogoutUserEvent — user session is invalidated after any database switch.
  • DatabaseStatusBarViewModel.OnDbEvent(...) only handles LegacyStatus — other DbStatusArg.EventTypes are ignored.

4. Dependencies

Internal Dependencies (from source):

  • DTS.Common.*:
    • DTS.Common.Enums.Database.DbType
    • DTS.Common.Events.* (RaiseNotification, BusyIndicatorChangeNotification, DbStatusEvent, AppStatusEvent, PageErrorEvent, LogoutUserEvent)
    • DTS.Common.Storage.DatabaseServices (SetupForRemoteDb, SimpleDbTest, SetupLocal, BackupLocalDatabase, RestoreLocalDatabase, LOCAL_DB_FOLDER)
    • DTS.Common.Storage.DatabaseServices (via DbOperations, LocalOnlyOperations)
    • DTS.Common.Interface.Database.* (e.g., IDatabaseStatusBarView, IDatabaseCopyViewModel)
    • DTS.Common.Interface.* (e.g., IStatusAndProgressBarView)
    • DTS.Common.Utilities.Logging.APILogger
    • DTS.Common.Interactivity.* (InteractionRequest, Notification, Confirmation)
  • Prism Framework:
    • Prism.Events.IEventAggregator, Prism.Regions.IRegionManager
    • Prism.Commands, Prism.Interactivity.InteractionRequest
  • Unity DI Container (IUnityContainer)
  • WPF (System.Windows.Media.Brush, System.Windows.Visibility)

External Dependencies:

  • SQL Server (via System.Data.SqlClient, DbOperations.Connection, LocalOnlyOperations)
  • Resources.StringResources (localized strings: "Local", "CopyingTable", "ClearingLocalDb", "EnablingConstraints", "SwitchFileNotFound")

Inferred Consumers:

  • Views (IDatabaseStatusBarView, IDatabaseSwitchView, IDatabaseCopyView) bind to these view models.
  • Event publishers (RaiseNotification, DbStatusEvent, AppStatusEvent, etc.) drive view model state changes.
  • DatabaseServices layer (DbOperations, LocalOnlyOperations) is called directly by these view models.

5. Gotchas

  • DatabaseStatusBarViewModel has two constructors — the parameterless one does not subscribe to events, so OnDbEvent, OnBusyIndicatorNotification, and OnRaiseNotification will not be triggered if used. This is likely a design flaw or legacy artifact.
  • DatabaseStatusBarViewModel.OnDbEvent only handles LegacyStatus — other status types (e.g., FailedToConnectToRemote) are silently ignored.
  • DatabaseCopyViewModel.CopyFunc() loads entire remote tables into memoryCopyRemoteTable fetches all rows via QueryDataSet before copying. This may cause OOM for large tables.
  • DatabaseCopyViewModel uses hardcoded table list (_allDBTables) — not dynamically fetched from DB schema. Duplicates exist ("DataPRODbVersion" and "tblDataPRODbVersion"), and missing tables will cause copy failures.
  • Batch size (MAX_BATCH_SIZE = 20) is arbitrary — comment notes it was tuned empirically to avoid SQL parameter limits (2100), but no validation ensures column count × rows ≤ 2100.
  • DatabaseSwitchViewModel.SwitchRemote() calls SwitchLocal() on failure — this may cause cascading failures or confusing UI state if local DB is also unavailable.
  • DatabaseStatusBarViewModel.ServerName is updated only in OnDbEvent for LegacyStatus — if InitializeValues is not called first, ServerName remains null/empty, leading to incorrect ActiveDbName.
  • DatabaseCopyViewModel.InitializeAsync() resolves views/models twice — two separate Resolve calls for IStatusAndProgressBarView/IStatusAndProgressBarViewModel per progress bar, potentially creating duplicate view model instances.
  • No cancellation supportCopyDatabase() and SwitchRemote()/SwitchLocal() lack cancellation tokens or progress callbacks for user-initiated aborts.
  • DbOperations._usingCentralizedDB is a static field — shared across the app domain; changes in one view model affect others unexpectedly.
  • DatabaseStatusBarViewModel.ActiveDbName returns "" for unhandled DbType — no fallback or exception on unknown types.
  • DatabaseCopyViewModel uses sp_msforeachtable — undocumented, unsupported SQL Server stored procedure; may break on future SQL Server versions or non-standard DB configurations.