Skip to content

SAIF.Data architecture

SAIF.Data is the data layer of the SAIF.SAIFCode.Core package: it defines roughly 450 NHibernate-mapped entity models, 37 query providers that read them through IRepositoryFactory/NHibernate LINQ, two outbound HTTP clients to Guidewire ClaimCenter and the Medical Billing API, an Autofac registration extension for those clients, and a set of in-memory test-data seeding helpers that ship in the production assembly (saif-data-analysis.md Architecture findings).

Responsibilities

  • Define the entity and DTO model surface (~461 public types under SAIF.Data.Model.*) that SAIF.Data.NHibernate maps to Oracle tables; the persistence mappings themselves live outside this library.
  • Implement 37 query providers, each deriving from the external QueryProviderBase, encapsulating LINQ queries over Factory.GetRepository<T>().Query() plus related business logic (saif-data-analysis.md Public surface summary).
  • Provide two outbound HTTP clients — MedicalBillingApiService and CCClaimApiService — that call the Medical Billing API and the Guidewire CC Claim Data API respectively, the latter deriving from SAIF.Data.Guidewire.Clients.HttpClientBase.
  • Register the data API clients, a Polly cache policy, and Microsoft.Extensions Options/MemoryCache infrastructure through ContainerBuilderExtensions.AddDataClients, the library's only public Autofac entry point.
  • Ship TestRepository/** in-memory seeding builders and extensions for test setup, even though they are compiled into the production assembly.

Component boundaries

  • Model/: entity and DTO definitions (Claims, Bills, Ebilling, Collections, Legal, Policies, Providers, Documents, OutputDocuments, Tasks, Rct, Agencies, and others); mapped externally by SAIF.Data.NHibernate.
  • Queries/: 37 query providers and their I*QueryProvider interfaces, plus CCClaimApiService.
  • Clients/: HttpClientBase (local abstract base), MedicalBillingApiService, and its interface.
  • Configuration/: ContainerBuilderExtensions, the sole Autofac registration surface.
  • Interfaces/Repositories/: repository interface groups (Groups, Imaging, OutputDocuments).
  • TestRepository/: in-memory seeding builders and extensions shipped in the production assembly.

Interaction model

Consumers such as SAIF.Services, SAIF.Domain, and the Web.Mvc5 front end resolve query providers (registered outside this library, for example in DependencyMaps/*) and call them; each provider executes NHibernate LINQ through IRepositoryFactory/IRepository<T>, whose runtime implementation is supplied by SAIF.Data.NHibernate via the external SAIF.Framework.Data.NHibernate package. Some providers combine this with calls into SAIF.Data.Guidewire's HTTP clients for hybrid Oracle/Guidewire data sourcing — for example ClaimQueryProvider uses IClaimDataApiClient/ICCClaimApiService for claim, MCO, and financial data, and LegalQueryProvider.GetClaimIdForCase calls the CC API before falling back to legacy identifiers (saif-data-analysis.md Architecture findings, OP-SD-15, OP-SD-18). ContainerBuilderExtensions.AddDataClients is the entry point hosts call to wire up the Guidewire clients, credentials, and the Polly cache policy at startup.

Architecture diagram

The following diagram shows how consumers reach the entity/query layer, the NHibernate-backed data path, and the Guidewire/Medical Billing HTTP path.

flowchart TD
    Consumers["SAIF.Services / SAIF.Domain /<br>SAIF.Web.Mvc5 callers"] --> QP["37 query providers<br>(QueryProviderBase)"]
    QP --> Repo["IRepositoryFactory /<br>IRepository&lt;T&gt;.Query() (NHibernate LINQ)"]
    Repo --> NH["SAIF.Data.NHibernate<br>ClassMaps and repositories"]
    QP --> CCApi["CCClaimApiService"]
    QP --> MBApi["MedicalBillingApiService"]
    CCApi --> GWBase["SAIF.Data.Guidewire<br>HttpClientBase"]
    MBApi --> LocalBase["SAIF.Data.Clients<br>HttpClientBase"]
    GWBase --> GWAPI["Guidewire ClaimCenter API"]
    LocalBase --> MBAPI["Medical Billing REST API"]
    Config["ContainerBuilderExtensions.AddDataClients"] --> CCApi
    Config --> MBApi

Sequence diagram

The following diagram shows a representative hybrid call: validating and retrieving a claim through the Guidewire CC Claim Data API (OP-SD-04).

sequenceDiagram
    participant Caller as SAIF.Services caller
    participant CCApi as CCClaimApiService
    participant GWBase as Guidewire HttpClientBase
    participant CC as Guidewire ClaimCenter API
    Caller->>CCApi: ValidateClaim(claimId)
    CCApi->>GWBase: GetAsyncCached<T>(GET v1/GeneralClaimData/Claim/{id})
    GWBase->>CC: GET v1/GeneralClaimData/Claim/{id}
    CC-->>GWBase: 200 OK / claim data
    GWBase-->>CCApi: Deserialized response
    CCApi-->>Caller: true/false

Design constraints

  • There is no composition root, session, or transaction management in this library; units of work are supplied by external SAIF.Framework.* packages (saif-data-analysis.md Architecture findings/Boundaries).
  • Data sourcing is hybrid: several query providers combine Oracle-backed entity reads with Guidewire REST calls, and several legacy WCIS claim-activity queries now throw NotImplementedException with the message "data retired," indicating an in-flight migration (SD-BR-045 Retired WCIS claim activity queries are unsupported).
  • Writes performed directly in this library are rare and limited to in-memory entity mutation (EbillQueryProvider.SetCompoundDrugForAllServiceLinesForTheBill, SD-BR-052 Multiple prescription numbers mark all NDC lines as compound drug, plus model helper methods); persistence is committed by the caller's IUnitOfWork.
  • TestRepository/** seeding helpers are compiled into the production assembly; whether that is intentional is unknown (saif-data-analysis.md Open questions item 5)**.
  • Query provider registration and lifetimes are decided outside this library, for example in DependencyMaps/* (saif-data-analysis.md Architecture findings).
  • HttpClientBase.GetAsyncCached builds its cache key from type, URL, ensureSuccess, and body hash only, with no per-user component, so downstream per-user data-level filtering is not reflected in the shared 30-second cache (saif-data-security-analysis.md Security concerns, Medium severity)*.
  • Credentials are decrypted with SystemHashUtil and split on | without a length check; a malformed secure setting raises IndexOutOfRangeException rather than a descriptive error (saif-data-config-analysis.md Secure settings catalog)*.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • Data/SAIF.Data/SAIF.Data.csproj
  • Data/SAIF.Data/Configuration/ContainerBuilderExtensions.cs
  • Data/SAIF.Data/Clients/HttpClientBase.cs
  • Data/SAIF.Data/Clients/MedicalBillingApiService.cs
  • Data/SAIF.Data/Queries/Claims/CCClaimApiService.cs
  • Data/SAIF.Data/Queries/Claims/ClaimQueryProvider.cs
  • Data/SAIF.Data/Queries/Legal/LegalQueryProvider.cs
  • Data/SAIF.Data/Queries/Claims/Ebilling/EbillQueryProvider.cs
  • Data/SAIF.Data/TestRepository/**