193 lines
13 KiB
Markdown
193 lines
13 KiB
Markdown
---
|
|
source_files:
|
|
- DataPRO/Modules/Database/DatabaseServices/ViewModel/DatabaseStatusBarViewModel.cs
|
|
- DataPRO/Modules/Database/DatabaseServices/ViewModel/DatabaseSwitchViewModel.cs
|
|
- DataPRO/Modules/Database/DatabaseServices/ViewModel/DatabaseCopyViewModel.cs
|
|
generated_at: "2026-04-17T15:41:29.202299+00:00"
|
|
model: "zai-org/GLM-5-FP8"
|
|
schema_version: 1
|
|
sha256: "f011aeacca70c45c"
|
|
---
|
|
|
|
# Database ViewModels Documentation
|
|
|
|
## 1. Purpose
|
|
|
|
This module provides three MVVM ViewModels for database management within the `DatabaseServices` namespace:
|
|
|
|
- **DatabaseStatusBarViewModel**: Manages the database status bar UI, displaying the active database connection (Local vs Remote) and providing visual feedback (red background when disconnected from remote in hybrid mode).
|
|
- **DatabaseSwitchViewModel**: Handles switching between local and remote database connections, including connection testing, authentication setup, and forcing user re-login after database switches.
|
|
- **DatabaseCopyViewModel**: Implements database copy functionality to synchronize a remote database to a local database, including table-by-table copying with identity column handling and constraint management.
|
|
|
|
All three ViewModels follow the Prism MVVM pattern, use MEF for dependency injection with shared creation policy, and integrate with the application's event aggregation system.
|
|
|
|
---
|
|
|
|
## 2. Public Interface
|
|
|
|
### DatabaseStatusBarViewModel
|
|
|
|
**Implements:** `IDatabaseStatusBarViewModel`
|
|
|
|
| Member | Signature | Description |
|
|
|--------|-----------|-------------|
|
|
| `View` | `public IDatabaseStatusBarView View { get; set; }` | The associated view instance; DataContext is set to `this` in constructor. |
|
|
| `DatabaseType` | `public DbType DatabaseType { get; private set; }` | The configured database type (LocalOnly, RemoteOnly, RemoteLocalHybrid). |
|
|
| `ServerName` | `public string ServerName { get; private set; }` | Name of the database server; "Local" when not remote connected. |
|
|
| `RemoteConnected` | `public bool RemoteConnected => DbOperations._usingCentralizedDB;` | Indicates if currently connected to centralized/remote database. |
|
|
| `ActiveDbName` | `public string ActiveDbName { get; }` | Computed display name based on DatabaseType and connection state. Returns localized "Local" string or server name. |
|
|
| `BackgroundBrush` | `public Brush BackgroundBrush { get; }` | Returns `Brushes.Red` when hybrid mode is disconnected from remote; otherwise `Brushes.Transparent`. |
|
|
| `InitializeValues` | `public void InitializeValues(DbType dbType, string serverName, bool remoteConnected)` | Initializes the ViewModel's state and triggers PropertyChanged for `ActiveDbName` and `BackgroundBrush`. |
|
|
| `OnPropertyChanged` | `public void OnPropertyChanged(string propertyName)` | Raises the `PropertyChanged` event. |
|
|
| `NotificationRequest` | `public InteractionRequest<Notification> NotificationRequest { get; }` | Prism interaction request for notifications. |
|
|
| `ConfirmationRequest` | `public InteractionRequest<Confirmation> ConfirmationRequest { get; }` | Prism interaction request for confirmations. |
|
|
| `IsBusy` | `public bool IsBusy { get; set; }` | Bound to busy indicator state. |
|
|
| `IsMenuIncluded` | `public bool IsMenuIncluded { get; set; }` | Controls menu visibility. |
|
|
| `IsNavigationIncluded` | `public bool IsNavigationIncluded { get; set; }` | Controls navigation visibility. |
|
|
| `IsDirty` | `public bool IsDirty { get; private set; }` | Tracks unsaved changes state. |
|
|
| `Cleanup` / `CleanupAsync` | `public void Cleanup()` / `public Task CleanupAsync()` | No-op cleanup methods. |
|
|
| `Initialize` overloads | `void Initialize()`, `void Initialize(object)`, `void Initialize(object, object)` | No-op initialization methods. |
|
|
| `InitializeAsync` overloads | `Task InitializeAsync()`, `Task InitializeAsync(object)` | Return `Task.CompletedTask`. |
|
|
| `Activated` | `public void Activated()` | No-op activation method. |
|
|
| `Unset` | `public void Unset()` | No-op unset method. |
|
|
|
|
**Constructor:**
|
|
```csharp
|
|
public DatabaseStatusBarViewModel(
|
|
IDatabaseStatusBarView view,
|
|
IRegionManager regionManager,
|
|
IEventAggregator eventAggregator,
|
|
IUnityContainer unityContainer)
|
|
```
|
|
|
|
---
|
|
|
|
### DatabaseSwitchViewModel
|
|
|
|
**Implements:** `IDatabaseSwitchViewModel`
|
|
|
|
| Member | Signature | Description |
|
|
|--------|-----------|-------------|
|
|
| `View` | `public IDatabaseSwitchView View { get; set; }` | The associated view instance. |
|
|
| `DefaultDbName` | `public string DefaultDbName { get; private set; }` | Default database name for connections. |
|
|
| `DbHost` | `public string DbHost { get; private set; }` | Remote database host address. |
|
|
| `NTLMAuthentication` | `public bool NTLMAuthentication { get; private set; }` | Whether NTLM authentication is enabled. |
|
|
| `DbUser` | `public string DbUser { get; private set; }` | Database username for SQL authentication. |
|
|
| `DbPassword` | `public string DbPassword { get; private set; }` | Database password for SQL authentication. |
|
|
| `RemoteIsActive` | `public bool RemoteIsActive => DbOperations._usingCentralizedDB;` | Indicates if remote database is currently active. |
|
|
| `SwitchRemote` | `public void SwitchRemote()` | Switches to remote database connection. Tests connection, falls back to local on failure, publishes `DbStatusEvent` and `LogoutUserEvent`. |
|
|
| `SwitchLocal` | `public void SwitchLocal()` | Switches to local database. Validates local files exist, publishes status events and forces logout. |
|
|
| `InitializeDbSettings` | `public void InitializeDbSettings(string defaultDbName, string dbHost, bool ntlmAuthentication, string dbUser, string dbPassword)` | Stores database connection settings for use by switch methods. |
|
|
| `IsBusy`, `IsMenuIncluded`, `IsNavigationIncluded`, `IsDirty` | Same as DatabaseStatusBarViewModel | Standard ViewModel properties. |
|
|
| `NotificationRequest`, `ConfirmationRequest` | Same as DatabaseStatusBarViewModel | Prism interaction requests. |
|
|
| Lifecycle methods | Same pattern as DatabaseStatusBarViewModel | `Cleanup`, `CleanupAsync`, `Initialize*`, `Activated`, `Unset` are no-ops or return completed tasks. |
|
|
|
|
**Constructor:**
|
|
```csharp
|
|
public DatabaseSwitchViewModel(
|
|
IDatabaseSwitchView view,
|
|
IRegionManager regionManager,
|
|
IEventAggregator eventAggregator,
|
|
IUnityContainer unityContainer)
|
|
```
|
|
|
|
---
|
|
|
|
### DatabaseCopyViewModel
|
|
|
|
**Implements:** `IDatabaseCopyViewModel`
|
|
|
|
| Member | Signature | Description |
|
|
|--------|-----------|-------------|
|
|
| `View` | `public IDatabaseCopyView View { get; set; }` | The associated view instance. |
|
|
| `DatabaseType` | `public DTS.Common.Enums.Database.DbType DatabaseType { get; private set; }` | Current database type configuration. |
|
|
| `DbName` | `public string DbName { get; private set; }` | Name of the database being copied. |
|
|
| `CopyEnabled` | `public bool CopyEnabled => DatabaseType == DbType.RemoteLocalHybrid && DbOperations._usingCentralizedDB;` | Copy is only enabled in hybrid mode when connected to remote. |
|
|
| `IsCopyVisible` | `public bool IsCopyVisible { get; set; }` | Controls visibility of copy UI; defaults to `true`. |
|
|
| `OverallProgressBarView` | `public IStatusAndProgressBarView OverallProgressBarView { get; private set; }` | Progress bar view for overall copy progress. |
|
|
| `CurrentTaskProgressBarView` | `public IStatusAndProgressBarView CurrentTaskProgressBarView { get; private set; }` | Progress bar view for current table copy progress. |
|
|
| `CopyDatabase` | `public void CopyDatabase()` | Initiates async database copy via `Task.Run(() => CopyFunc())`. Publishes `AppStatusEvent.Busy`. |
|
|
| `InitializeState` | `public void InitializeState(DTS.Common.Enums.Database.DbType dbType, string dbName)` | Sets up initial state, resets progress bars, triggers `OnPropertyChanged("CopyEnabled")`. |
|
|
| `InitializeAsync` | `public Task InitializeAsync()` | Resolves and initializes progress bar views via Unity container. |
|
|
| `_allDBTables` | `private static readonly List<string>` | Hardcoded list of 73 database table names to copy. |
|
|
| `_tablesWithIdentities` | `private static readonly HashSet<string>` | Hardcoded set of 48 table names that have identity columns. |
|
|
| `MAX_BATCH_SIZE` | `private const int MAX_BATCH_SIZE = 20;` | Maximum rows per batch insert to avoid SQL Server's 2100 parameter limit. |
|
|
| `CurrentTaskBar` | `private const string CurrentTaskBar = "CurrentTaskStatus";` | Identifier for current task progress bar. |
|
|
| `OverallTaskBar` | `private const string OverallTaskBar = "OverallStatus";` | Identifier for overall progress bar. |
|
|
| Lifecycle methods | Same pattern as other ViewModels | Standard no-op implementations except `InitializeAsync`. |
|
|
|
|
**Constructor:**
|
|
```csharp
|
|
public DatabaseCopyViewModel(
|
|
IDatabaseCopyView view,
|
|
IRegionManager regionManager,
|
|
IEventAggregator eventAggregator,
|
|
IUnityContainer unityContainer)
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Invariants
|
|
|
|
### DatabaseStatusBarViewModel
|
|
- `ActiveDbName` returns empty string for unhandled `DbType` values (not LocalOnly, RemoteOnly, or RemoteLocalHybrid).
|
|
- `BackgroundBrush` only returns `Brushes.Red` for `DbType.RemoteLocalHybrid` when `RemoteConnected` is false; all other cases return `Brushes.Transparent`.
|
|
- `RemoteConnected` is directly coupled to `DbOperations._usingCentralizedDB` static field.
|
|
|
|
### DatabaseSwitchViewModel
|
|
- `SwitchRemote` always publishes `LogoutUserEvent` with reason `DatabaseSwitch` on success.
|
|
- `SwitchRemote` calls `SwitchLocal()` as fallback if connection test fails.
|
|
- `SwitchLocal` checks for local database file existence before proceeding; returns early with error if files not found.
|
|
- `SwitchLocal` always publishes `LogoutUserEvent` with reason `DatabaseSwitch` on success.
|
|
|
|
### DatabaseCopyViewModel
|
|
- `CopyEnabled` is only true when `DatabaseType == DbType.RemoteLocalHybrid` AND `DbOperations._usingCentralizedDB` is true.
|
|
- Copy operation disables constraints before copying and re-enables them after.
|
|
- If copy fails, attempts to restore from backup via `DTS.Common.Storage.DatabaseServices.RestoreLocalDatabase(DbName)`.
|
|
- Batch inserts are limited to `MAX_BATCH_SIZE` (20 rows) or when parameter count would exceed 2100.
|
|
- Identity insert is enabled/disabled per batch for tables in `_tablesWithIdentities`.
|
|
- `DASId` columns with value 0 are explicitly set to NULL in the Channels table after copy.
|
|
|
|
---
|
|
|
|
## 4. Dependencies
|
|
|
|
### External Dependencies (from imports)
|
|
- **Prism Framework:** `Prism.Events`, `Prism.Regions`, `Prism.Commands` - Event aggregation, region management, commanding
|
|
- **Unity Container:** `Unity` - Dependency injection container
|
|
- **MEF:** `System.ComponentModel.Composition` - Part creation policy
|
|
- **WPF:** `System.Windows.Media`, `System.ComponentModel` - UI types, INotifyPropertyChanged
|
|
- **DTS.Common.Enums.Database:** `DbType` enum
|
|
- **DTS.Common.Events:** `RaiseNotification`, `BusyIndicatorChangeNotification`, `AppStatusEvent`, `AppStatusArg`, `ProgressBarEvent`, `ProgressBarEventArg`, `PageErrorEvent`, `PageErrorArg`
|
|
- **DTS.Common.Events.Database:** `DbStatusEvent`, `DbStatusArg`, `LogoutUserEvent`, `LogoutUserArg`
|
|
- **DTS.Common.Interactivity:** `InteractionRequest<T>`, `Notification`, `Confirmation`, `NotificationContentEventArgs`
|
|
- **DTS.Common.Interface.Database:** `IDatabaseStatusBarView`, `IDatabaseSwitchView`, `IDatabaseCopyView`, `IDatabaseStatusBarViewModel`, `IDatabaseSwitchViewModel`, `IDatabaseCopyViewModel`
|
|
- **DTS.Common.Interface:** `IStatusAndProgressBarView`, `IStatusAndProgressBarViewModel`
|
|
- **DTS.Common.Storage:** `DbOperations`, `LocalOnlyOperations`, `DatabaseServices` (static class)
|
|
- **DTS.Common.Utilities.Logging:** `APILogger`
|
|
- **DTS.Common.Utils.Database:** `CheckLocalDatabaseFilesExist`
|
|
- **Resources.StringResources:** Localized strings
|
|
|
|
### Static Couplings
|
|
- `DbOperations._usingCentralizedDB` - Static field accessed directly by all three ViewModels
|
|
- `DbOperations.Connection.Server` - Server name accessed directly
|
|
- `DbOperations.GetSQLCommand()` - SQL command creation for remote DB
|
|
- `LocalOnlyOperations.GetSQLCommand()` - SQL command creation for local DB
|
|
- `LocalOnlyOperations.BeginStatement`, `LocalOnlyOperations.CommitStatement` - Transaction statements
|
|
- `LocalOnlyOperations.CreateParam()` - Parameter creation helper
|
|
|
|
---
|
|
|
|
## 5. Gotchas
|
|
|
|
### XML Documentation Mismatch
|
|
- `DatabaseStatusBarViewModel` and `DatabaseSwitchViewModel` XML summary comments state "this class handles DatabaseCopy functionality" which is incorrect (copy-paste error from `DatabaseCopyViewModel`).
|
|
|
|
### Parameterless Constructors
|
|
- All three ViewModels have public parameterless constructors in addition to the DI constructor. The parameterless constructors perform no initialization, which could lead to null reference exceptions if used incorrectly.
|
|
|
|
### Static Table Lists
|
|
- `DatabaseCopyViewModel._allDBTables` and `_tablesWithIdentities` are hardcoded lists. Any database schema changes require code updates. Comment in source states: "I'd like to do this through SQL, but ran into problems".
|
|
|
|
### Thread Safety Concerns
|
|
- `DatabaseCopyViewModel.CopyDatabase()` uses `Task.Run()` to execute `CopyFunc()` on a background thread, but `SetStatus()` publishes UI events directly. The `BusyIndicatorChangeNotification` subscription in `DatabaseStatusBarViewModel` uses `ThreadOption.PublisherThread` with `keepSubscriberReferenceAlive: true |