LoadDimensionMembers
Overview
LoadDimensionMembersTask synchronizes dimension members from entity tables (Facility, Provider, Insurance, BillType, ChargeType, ProviderType) into the DimensionMember table. This task refreshes the metadata used for filtering, reporting, and hierarchical navigation in dashboards and pricing rules.
Use this task when: You've added or modified facilities, providers, insurances, bill types, charge types, or provider types and need to update the dimension member cache used across the application.
Don't use this task when: You're making changes to pricing or visit data that don't affect the core entity tables. This task is purely for metadata synchronization, not for data processing.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
LoadInsurance |
bool |
No | true |
Load Insurance dimension members from the Insurance table |
LoadQuoteInsurance |
bool |
No | true |
Load QuoteInsurance dimension members (filtered to contract insurances only) |
LoadEligibilityInsurance |
bool |
No | true |
Load EligibilityInsurance dimension members (filtered to eligibility-enabled insurances only) |
LoadFacility |
bool |
No | true |
Load Facility dimension members from the Facility table |
LoadProvider |
bool |
No | true |
Load Provider dimension members from the Provider table |
LoadProviderType |
bool |
No | true |
Load ProviderType dimension members from the ProviderType table |
LoadBillType |
bool |
No | true |
Load BillType dimension members from the BillType table |
LoadChargeType |
bool |
No | true |
Load ChargeType dimension members from the ChargeType table |
Note: All parameters default to true. To selectively refresh only specific dimensions, create a task with LoadDimensionMembersTask(false) constructor and set only desired dimensions to true.
Execution Flow
flowchart TD
A[Start LoadDimensionMembers] --> B{LoadInsurance?}
B -->|Yes| C[Load Insurance Dimensions]
B -->|No| D{LoadFacility?}
C --> C1[Delete existing Insurance members]
C1 --> C2[Delete existing QuoteInsurance members if enabled]
C2 --> C3[Delete existing EligibilityInsurance members if enabled]
C3 --> C4[Load all insurances from Insurance table]
C4 --> C5[Save Insurance dimension members]
C5 --> C6[Save QuoteInsurance for contract insurances]
C6 --> C7[Save EligibilityInsurance for eligibility-enabled insurances]
C7 --> D
D -->|Yes| E[Load Facility Dimension]
D -->|No| F{LoadBillType?}
E --> E1[Get parent dimension key FacilityGroup or FacilityType]
E1 --> E2[Delete existing Facility members]
E2 --> E3[Load all facilities]
E3 --> E4[Save Facility dimension members with parent hierarchy]
E4 --> F
F -->|Yes| G[Load BillType Dimension]
F -->|No| H{LoadProviderType?}
G --> G1[Delete existing BillType members]
G1 --> G2[Load all bill types]
G2 --> G3[Save BillType dimension members]
G3 --> H
H -->|Yes| I[Load ProviderType Dimension]
H -->|No| J{LoadProvider?}
I --> I1[Delete existing ProviderType members]
I1 --> I2[Load all provider types]
I2 --> I3[Save ProviderType dimension members]
I3 --> J
J -->|Yes| K[Load Provider Dimension]
J -->|No| L{LoadChargeType?}
K --> K1[Get parent dimension key usually ProviderType]
K1 --> K2[Delete existing Provider members]
K2 --> K3[Load all providers]
K3 --> K4[Save Provider dimension members with parent hierarchy]
K4 --> L
L -->|Yes| M[Load ChargeType Dimension]
L -->|No| Z[Complete]
M --> M1[Delete existing ChargeType members]
M1 --> M2[Load all charge types]
M2 --> M3[Save ChargeType dimension members]
M3 --> Z
style C5 fill:#e1f5ff
style E4 fill:#e1f5ff
style G3 fill:#e1f5ff
style I3 fill:#e1f5ff
style K4 fill:#e1f5ff
style M3 fill:#e1f5ff
Processing Algorithm
The task uses a delete-and-replace strategy for each dimension:
- Delete Phase: Remove all existing
DimensionMemberrecords for the target dimension - Load Phase: Retrieve all entities from the source table (e.g., all facilities from
Facilitytable) - Map Phase: For each entity, create or update a
DimensionMemberrecord with:MemberKey: The entity's primary key (e.g.,Facility.Key,Provider.ProviderID)DisplayName: The entity's display name (e.g.,Facility.Name,Provider.FullName)ParentKey: Optional parent dimension key for hierarchical relationships (e.g., Facility → FacilityGroup)
- Save Phase: Persist all dimension members to the
DimensionMembertable
Insurance Dimension Special Logic
Insurance dimensions have special filtering logic:
- Insurance: All insurance records are loaded
- QuoteInsurance: Only insurances where
IsContractInsurancereturnstrue(insurances with configured contracts) - EligibilityInsurance: Only insurances where
IsEligibilityInsurancereturnstrue(insurances with eligibility API configuration)
Example Execution
If you have:
- 5 Facilities
- 50 Providers (with ProviderType parent hierarchy)
- 100 Insurance records (80 have contracts, 60 have eligibility enabled)
- 10 BillTypes
- 200 ChargeTypes
- 8 ProviderTypes
The task will create:
- 5 Facility dimension members
- 50 Provider dimension members (with ProviderType parent links)
- 100 Insurance dimension members
- 80 QuoteInsurance dimension members (subset)
- 60 EligibilityInsurance dimension members (subset)
- 10 BillType dimension members
- 200 ChargeType dimension members
- 8 ProviderType dimension members
Total: 513 dimension member records
Usage Examples
Example 1: Full dimension refresh (default behavior)
// Load all dimensions - typical usage after initial setup or major entity changes
var task = new LoadDimensionMembersTask();
task.Execute(dataStore);
Example 2: Refresh only provider-related dimensions
// After adding new providers or provider types
var task = new LoadDimensionMembersTask(false) // Start with all flags = false
{
LoadProvider = true,
LoadProviderType = true
};
task.Execute(dataStore);
Example 3: Refresh only insurance dimensions
// After adding new insurances or modifying insurance contracts
var task = new LoadDimensionMembersTask(false)
{
LoadInsurance = true,
LoadQuoteInsurance = true,
LoadEligibilityInsurance = true
};
task.Execute(dataStore);
Example 4: Refresh facility hierarchy after configuration change
// After modifying facility groups or facility types
var task = new LoadDimensionMembersTask(false)
{
LoadFacility = true
};
task.Execute(dataStore);
Example 5: Automated refresh in entity save workflow
// Example from ProviderTypesPageDataManager.AfterSave
public override void AfterSave(bool changes)
{
if (changes)
{
LoadDimensionMembersTask task = new LoadDimensionMembersTask(false)
{
LoadProviderType = true,
};
task.Execute(dataStore);
// Clear dimension cache
dimensionCache.Remove(DimensionName.Provider.ToString());
dimensionCache.Remove(DimensionName.ProviderType.ToString());
}
}
Related Tasks Comparison
| Task | Use Case | Scope | Affects Pricing | Data vs Metadata |
|---|---|---|---|---|
| LoadDimensionMembers | Refresh dimension member metadata | Entity tables → DimensionMember | No | Metadata only |
LoadDataFile |
Import entity data from files | Files → Entity tables | Depends on entity | Data import |
ImportSql |
Import entity data from SQL queries | SQL query → Entity tables | Depends on entity | Data import |
ReprocessChangedConfigurations |
Reprocess data after config changes | Config changes → Queue | Yes | Data reprocessing |
UpdateDashboardTables |
Regenerate dashboard aggregations | Entity data → Dashboard tables | No | Aggregated data |
Key Difference: LoadDimensionMembers is purely a metadata synchronization task. It doesn't import or modify the underlying entity data (facilities, providers, etc.), it only refreshes the dimension member references used for filtering and reporting.
Performance Considerations
Database Impact
- Tables Read:
Insurance,Facility,Provider,ProviderType,BillType,ChargeType,DimensionMember - Tables Written:
DimensionMember(deletes and inserts) - Query Complexity: Simple
GetAll()operations on entity tables, then individual inserts for dimension members - Transaction Scope: Each dimension is processed independently (no cross-dimension transactions)
Optimization Tips
| Scenario | Recommendation | Rationale |
|---|---|---|
| After adding single provider | Use selective loading with only LoadProvider = true and LoadProviderType = true |
Avoids unnecessary work on other dimensions |
| After bulk entity import | Run full task once after all imports complete | More efficient than running after each import |
| Automated workflows | Only load affected dimensions in AfterSave hooks |
Minimizes database writes and execution time |
| Scheduled maintenance | Run full refresh during off-hours if dimension data can drift | Ensures dimension members stay synchronized |
Expected Performance
- Small systems (< 100 entities per dimension): < 1 second
- Medium systems (100-1000 entities per dimension): 1-5 seconds
- Large systems (> 1000 entities per dimension): 5-15 seconds
Note: Performance is primarily driven by the number of entities, not the data volume, as this task only processes metadata.
Error Handling
The task uses a fail-fast approach:
- If any dimension fails to load, the task throws an exception and stops execution
- Each dimension is loaded sequentially (not in parallel)
- Errors are logged via the
ILoggerinterface before being thrown - No rollback mechanism - completed dimensions remain loaded even if later dimensions fail
// Example error handling pattern in DimensionLoader<T>
public void Load()
{
logger.Log($"Loading {dimensionName} and existing Dimension Members");
List<T> entities = repo.GetAll(); // May throw if repo fails
List<DimensionMember> members = dimensionMemberRepo.GetDimensionMemberList(dimensionName.ToString());
DeleteDimensionMembers(); // May throw if delete fails
LoadMembers(entities, members); // May throw if save fails
logger.Log($"Done loading {dimensionName}");
}
Important: If the task fails mid-execution, some dimensions may be loaded while others are not. Re-running the task will reload all selected dimensions from scratch.
Common Pitfalls
| Issue | Problem | Solution |
|---|---|---|
| Dimension members not appearing in UI filters | Task wasn't run after adding new entities via API or direct SQL | Always run LoadDimensionMembers after bulk imports or direct database modifications |
| Parent hierarchy broken after entity changes | Task wasn't rerun after changing facility groups or provider types | Run task with affected dimensions enabled to rebuild parent-child relationships |
| QuoteInsurance missing valid insurances | Insurance lacks contract configuration | Verify insurance has ContractMap or FeeLogic contracts configured before expecting it in QuoteInsurance |
| EligibilityInsurance missing valid insurances | Insurance lacks eligibility API configuration | Verify insurance has ExternalApi eligibility configuration before expecting it in EligibilityInsurance |
| Dimension cache not refreshed | Application cache holds old dimension member data | Clear dimension cache after running task (see Example 5) |
| Performance degradation on large systems | Running full refresh unnecessarily | Use selective dimension loading (constructor with false parameter) to load only changed dimensions |
Code References
- Task Definition:
MDClarityCore/Backend/Tasks/LoadDimensionMembers/LoadDimensionMembersTask.cs:16 - Execute Method:
MDClarityCore/Backend/Tasks/LoadDimensionMembers/LoadDimensionMembersTask.cs:52 - Task Field Definition:
MDClarityCore/Backend/Tasks/LoadDimensionMembers/LoadDimensionMembersTaskField.cs:3 - DimensionLoader Implementation:
MDClarityCore/Backend/Tasks/LoadDimensionMembers/DimensionLoader.cs:9 - InsuranceDimensionLoader Implementation:
MDClarityCore/Backend/Tasks/LoadDimensionMembers/InsuranceDimensionLoader.cs:9 - DimensionManager Interface:
MDClarityCore/Backend/DimensionManager.cs:15 - Usage Example (ProviderTypes):
MDClarityCore/Backend/Common/Controllers/ProviderTypesPageDataManager.cs:73