LoadInsuranceDimensionMembers
Overview
LoadInsuranceDimensionMembersTask synchronizes insurance-related dimension members from the Insurance table into the DimensionMember table. It creates three separate dimension types: Insurance (all insurances), QuoteInsurance (contract insurances only), and EligibilityInsurance (eligibility-enabled insurances only).
Use this task when: You've added or modified insurances and need to selectively refresh only insurance-related dimensions without affecting other dimension types like facilities or providers.
Don't use this task when: You need to refresh all dimensions at once (use LoadDimensionMembersTask instead), or you're making changes that don't affect insurance entities.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
LoadInsurance |
bool |
No | true |
Load Insurance dimension members from the Insurance table (all insurance records) |
LoadQuoteInsurance |
bool |
No | true |
Load QuoteInsurance dimension members (filtered to insurances with configured contracts) |
LoadEligibilityInsurance |
bool |
No | true |
Load EligibilityInsurance dimension members (filtered to insurances with eligibility API configuration) |
Note: All parameters default to true. If all three are set to false, the task logs a warning and exits without making any changes.
Execution Flow
flowchart TD
A[Start LoadInsuranceDimensionMembers] --> B{All flags false?}
B -->|Yes| Z1[Log warning and exit]
B -->|No| C[Load all insurances from Insurance table]
C --> D[Load existing Insurance dimension members]
D --> E{LoadInsurance?}
E -->|Yes| F[Delete existing Insurance dimension members]
E -->|No| G
F --> G{LoadQuoteInsurance?}
G -->|Yes| H[Delete existing QuoteInsurance dimension members]
G -->|No| I
H --> I{LoadEligibilityInsurance?}
I -->|Yes| J[Delete existing EligibilityInsurance dimension members]
I -->|No| K
J --> K[Loop through each insurance]
K --> L{LoadInsurance enabled?}
L -->|Yes| M[Get or create DimensionMember for Insurance]
L -->|No| M1{Existing member found?}
M1 -->|Yes| M2[Use existing member]
M1 -->|No| M3[Log warning - no member will be created]
M2 --> N
M3 --> K
M --> M4[Save Insurance dimension member]
M4 --> N
N{LoadQuoteInsurance AND IsContractInsurance?}
N -->|Yes| O[Save QuoteInsurance dimension member]
N -->|No| P
O --> P
P{LoadEligibilityInsurance AND IsEligibilityInsurance?}
P -->|Yes| Q[Save EligibilityInsurance dimension member]
P -->|No| R
Q --> R
R{More insurances?}
R -->|Yes| K
R -->|No| S[Log summary counts]
S --> Z[Complete]
style F fill:#ffe1e1
style H fill:#ffe1e1
style J fill:#ffe1e1
style M4 fill:#e1f5ff
style O fill:#e1f5ff
style Q fill:#e1f5ff
style S fill:#fff4e1
Processing Algorithm
The task uses a delete-and-replace strategy with special filtering logic:
Phase 1: Deletion
Delete existing dimension members for each enabled dimension type:
- If
LoadInsurance = true: Delete allDimensionMemberrecords whereDimension = 'Insurance' - If
LoadQuoteInsurance = true: Delete allDimensionMemberrecords whereDimension = 'QuoteInsurance' - If
LoadEligibilityInsurance = true: Delete allDimensionMemberrecords whereDimension = 'EligibilityInsurance'
Phase 2: Load and Filter
For each insurance in the Insurance table:
Insurance Dimension:
- If
LoadInsurance = true: Create a newDimensionMemberwith key =Insurance.Key, displayName =Insurance.DisplayName - If
LoadInsurance = false: Use existing dimension member if found, otherwise skip this insurance for QuoteInsurance/EligibilityInsurance
- If
QuoteInsurance Dimension:
- Only save if
LoadQuoteInsurance = trueANDIsContractInsurance(insurance) = true IsContractInsurancereturnstrueif the insurance has at least oneContractMaprecord
- Only save if
EligibilityInsurance Dimension:
- Only save if
LoadEligibilityInsurance = trueANDIsEligibilityInsurance(insurance) = true IsEligibilityInsurancereturnstrueif the insurance has an associatedExternalAPIrecord for eligibility checking
- Only save if
Example Execution
Given 5 insurances in the Insurance table:
| Insurance Key | DisplayName | Has ContractMap? | Has ExternalAPI? |
|---|---|---|---|
| I-1 | Blue Cross | Yes | No |
| I-2 | Medicare | Yes | No |
| I-3 | Aetna | Yes | Yes |
| I-4 | Self Pay | No | No |
| I-5 | Cigna | No | Yes |
Result with all flags = true:
- Insurance dimension: 5 members (I-1, I-2, I-3, I-4, I-5)
- QuoteInsurance dimension: 3 members (I-1, I-2, I-3) - only those with ContractMap
- EligibilityInsurance dimension: 2 members (I-3, I-5) - only those with ExternalAPI
Total: 10 dimension member records created (5 + 3 + 2)
Usage Examples
Example 1: Full insurance dimension refresh (default behavior)
// Load all three insurance dimensions - typical usage after adding/modifying insurances
var task = new LoadInsuranceDimensionMembersTask();
task.Execute(dataStore);
Example 2: Refresh only base Insurance dimension
// After adding new insurances but before configuring contracts/eligibility
var task = new LoadInsuranceDimensionMembersTask()
{
LoadInsurance = true,
LoadQuoteInsurance = false,
LoadEligibilityInsurance = false
};
task.Execute(dataStore);
Example 3: Refresh only QuoteInsurance after contract changes
// After adding ContractMap records for existing insurances
var task = new LoadInsuranceDimensionMembersTask()
{
LoadInsurance = false, // Don't reload base Insurance
LoadQuoteInsurance = true, // Refresh QuoteInsurance filter
LoadEligibilityInsurance = false
};
task.Execute(dataStore);
Example 4: Refresh only EligibilityInsurance after API configuration
// After configuring ExternalAPI for insurances
var task = new LoadInsuranceDimensionMembersTask()
{
LoadInsurance = false,
LoadQuoteInsurance = false,
LoadEligibilityInsurance = true // Refresh EligibilityInsurance filter
};
task.Execute(dataStore);
Example 5: Automated refresh in entity save workflow
// Example pattern from InsuranceRepo.AfterSave
public override void AfterSave(Insurance insurance)
{
// After saving an insurance, refresh its dimension members
LoadInsuranceDimensionMembersTask task = new LoadInsuranceDimensionMembersTask();
task.Execute(dataStore);
// Clear dimension cache
dimensionCache.Remove(DimensionName.Insurance.ToString());
dimensionCache.Remove(DimensionName.QuoteInsurance.ToString());
dimensionCache.Remove(DimensionName.EligibilityInsurance.ToString());
}
Related Tasks Comparison
| Task | Use Case | Insurance Dimensions | Other Dimensions | Performance |
|---|---|---|---|---|
| LoadInsuranceDimensionMembers | Refresh only insurance dimensions | Yes (3 types) | No | Low (insurance-only) |
LoadDimensionMembers |
Refresh all dimension types | Yes (3 types) | Yes (5 types) | Medium (all dimensions) |
LoadDataFile |
Import insurance data from files | No | No | Medium (data import) |
ImportSql |
Import insurance data from SQL | No | No | Medium (data import) |
Key Differences:
LoadInsuranceDimensionMembersTaskis a specialized subset ofLoadDimensionMembersTaskthat only handles insurance-related dimensions- Use
LoadInsuranceDimensionMembersTaskwhen you want to avoid reloading provider, facility, bill type, charge type, and provider type dimensions LoadDimensionMembersTaskinternally callsLoadInsuranceDimensionMembersTaskfor the insurance portion
Performance Considerations
Database Impact
- Tables Read:
Insurance,ExternalAPI(via InsuranceRepo),ContractMap(via InsuranceRepo),DimensionMember - Tables Written:
DimensionMember(deletes and inserts) - Query Complexity:
- Simple
GetAll()on Insurance table - One ContractMap query per insurance (for QuoteInsurance filtering)
- One ExternalAPI query per insurance (for EligibilityInsurance filtering)
- Individual inserts for dimension members
- Simple
- Transaction Scope: Each dimension member save is independent (no transactions)
Optimization Tips
| Scenario | Recommendation | Rationale |
|---|---|---|
| After adding single insurance | Use default settings (all flags = true) | Ensures all three dimension types are synchronized |
| After adding ContractMap only | Set LoadInsurance = false, LoadQuoteInsurance = true, LoadEligibilityInsurance = false |
Avoids unnecessary work on unchanged dimensions |
| After adding ExternalAPI only | Set LoadInsurance = false, LoadQuoteInsurance = false, LoadEligibilityInsurance = true |
Minimizes database writes |
| After bulk insurance import | Run once after all imports complete | More efficient than running after each insurance |
| Scheduled maintenance | Run with all flags = true during off-hours | Ensures dimension members stay synchronized |
Expected Performance
- Small systems (< 100 insurances): < 1 second
- Medium systems (100-500 insurances): 1-3 seconds
- Large systems (> 500 insurances): 3-10 seconds
Note: Performance depends on the number of insurances and the filtering queries for ContractMap and ExternalAPI lookups.
Error Handling
The task uses a continue-on-error approach for individual insurances but fail-fast for structural errors:
- If loading insurances from the database fails, the task throws an exception immediately
- If an individual insurance fails to save, the error is logged but processing continues for remaining insurances
- All errors are logged via the
ILoggerinterface - Completed dimension member saves are not rolled back if later insurances fail
// Example from InsuranceDimensionLoader
foreach (Insurance insurance in insurances)
{
logger.Log($"Loading dimensions for insurance: {insurance.DisplayName ?? \"No Name\"} ({insurance.Key})");
try
{
DimensionMember member = GetMember(loadBaseInsurance, insuranceMembers, insurance);
if (loadBaseInsurance)
{
dimensionMemberRepo.SaveDimensionMember(member);
insuranceSaved++;
}
// ... continue with QuoteInsurance and EligibilityInsurance
}
catch (Exception ex)
{
logger.Log($"Error processing insurance {insurance.Key}: {ex.Message}");
// Continue to next insurance
}
}
Important: If the task fails mid-execution, some dimension members may be saved while others are not. Re-running the task will reload all selected dimensions from scratch (due to delete-and-replace strategy).
Common Pitfalls
| Issue | Problem | Solution |
|---|---|---|
| QuoteInsurance missing valid insurances | Insurance lacks ContractMap configuration | Verify insurance has at least one ContractMap record before expecting it in QuoteInsurance dimension |
| EligibilityInsurance missing valid insurances | Insurance lacks ExternalAPI eligibility configuration | Verify insurance has an associated ExternalAPI record with eligibility settings |
| LoadInsurance = false and no existing members | Setting LoadInsurance = false when no Insurance dimension members exist will prevent QuoteInsurance/EligibilityInsurance from being created |
Always run with LoadInsurance = true at least once, or ensure Insurance dimension members already exist |
| Dimension members not appearing in UI filters | Task wasn't run after adding insurances via API or direct SQL | Always run task after bulk imports or direct database modifications |
| All flags set to false | Task logs warning and exits without making changes | Ensure at least one flag is true |
| Dimension cache not refreshed | Application cache holds old dimension member data | Clear dimension cache after running task (see Example 5) |
Code References
- Task Definition:
MDClarityCore/Backend/Tasks/LoadDimensionMembers/LoadInsuranceDimensionMembersTask.cs:9 - Execute Method:
MDClarityCore/Backend/Tasks/LoadDimensionMembers/LoadInsuranceDimensionMembersTask.cs:26 - Task Field Definition:
MDClarityCore/Backend/Tasks/LoadDimensionMembers/LoadInsuranceDimensionMembersTaskField.cs:5 - InsuranceDimensionLoader:
MDClarityCore/Backend/Tasks/LoadDimensionMembers/InsuranceDimensionLoader.cs:9 - Load Method:
MDClarityCore/Backend/Tasks/LoadDimensionMembers/InsuranceDimensionLoader.cs:25 - IsContractInsurance Logic:
MDClarityCore/Backend/Common/Implementations/Repositories/EntityRepos/InsuranceRepo.cs:64 - IsEligibilityInsurance Logic:
MDClarityCore/Backend/Common/Implementations/Repositories/EntityRepos/InsuranceRepo.cs:59 - Integration Tests:
MDClarityCore/MDClarityTest/Tests/IntegrationTests/Backend/General Tasks/LoadInsuranceDimensionMembersTaskTests.cs:16