---
title: SAIF.Framework.Core architecture
summary: Architectural responsibilities, boundaries, and interaction patterns for the SAIF Business Object Framework (BOF) core library.
status: draft
owner: <owner>
last_reviewed: 2026-07-23
library: SAIF.Framework.Core
reference_type: package
---

# SAIF.Framework.Core architecture

`SAIF.Framework.Core` is the foundational Business Object Framework (BOF) layer of the repository (frameworkDensity: 0 — it is the framework's core; other repository libraries depend on it, not vice versa). It defines the abstract contracts and base implementations that all domain-specific business-object libraries inherit from (`clsBusinessBase`, `clsBusinessCollectionBase(Of ItemType)`, `IBusinessCriteria`), the data-access plumbing (`IDataPortalInfo`, `IDataAccess`, Oracle/SQL Server data layers), and cross-cutting concerns (business rules engine, smart values, property tracking, XML/report building). Two generations of several subsystems — the business rules engine and smart value types — coexist side by side in the same assembly under `V1\` and `V2\` folders/namespaces.

## Responsibilities
- Provide the abstract business-object base classes (`clsBusinessBase`, `clsBusinessCollectionBase`) that all domain business objects in the repository inherit from, including n-level undo (`BeginEdit`/`CancelEdit`/`ApplyEdit`), object linking (`ILinkItem`), and collection traversal (`ITraversion`).
- Provide a parallel REST/API-oriented business-object model (`clsBusinessApiBase`, `clsBusinessCollectionApiBase`, `clsBusinessApiCriteriaBase`) built on `RestSharp`, for business objects backed by web APIs rather than direct SQL.
- Abstract database access behind `IDataPortalInfo`/`IDataAccess` so business objects are decoupled from the concrete Oracle or SQL Server driver in use (`IDataLayer`, implemented by `clsMSOracleDataLayer` and `clsSQLDataLayer`).
- Host the business rules engine (`clsRulesManager` in V1, `RuleManager` in V2) that stores and invokes rule-handler delegates and tracks broken-rule results.
- Supply DB-null-safe "smart value" property wrapper types (`clsSmartString`/`clsSmartDate`/`clsSmartDecimal` in V1; `SmartString`/`SmartDate`/`SmartDecimal`/`SmartInteger` in V2) used throughout BOF business objects.
- Supply supporting cross-cutting infrastructure: property-change tracking (`TrackedProperty`/`TrackedProperties`, `TrackedApiProperty`/`TrackedApiProperties`), code-table/lookup abstractions (`clsCodeTableBase`, `clsCodeCollection`), validation helpers (`clsValidation`, `clsCharacterAnalyzer`), XML/report building (`clsReportSpecification`, `clsReportXMLBuilder`, `SAIFXDocument`), and environment/preference utilities (`clsProperties`, `SAIFEnvironment`, `Preference`/`PreferenceData`).

## Component boundaries
- **Classic business-object hierarchy (V1\BaseItems)**: `clsBusinessBase` (MustInherit; inherits `clsUndoableBase`; implements `IEditableObject`, `ICloneable`, `IDataErrorInfo`, `ISerializationNotification`, `ILinkItem`) and `clsBusinessCollectionBase`/`clsBusinessCollectionBase(Of ItemType)` (inherits `clsSortableCollectionBase`; implements `ICloneable`, `ISerializationNotification`, `ITraversion`, `IDataErrorInfo`). Each `clsBusinessBase` instance owns a `clsRulesManager` (`m_Rules`) exposed via the `Rules` property. Criteria support is provided by `clsBusinessCriteriaBase` (all five SQL properties overridable) and `clsRetrieveOnlyBusinessCriteria` (throws `ApplicationException` for Create/Insert/Update/Delete SQL, leaving only Retrieve).
- **API-based business-object hierarchy (V1\Api)**: `clsBusinessApiBase` (inherits `clsUndoableApiBase`) and `clsBusinessCollectionApiBase` mirror the classic hierarchy's shape but are backed by REST calls instead of SQL. `clsBusinessApiCriteriaBase` implements `IBusinessApiCriteria` (which extends `IBusinessCriteria`) with all five SQL properties overridable but empty by design — API-backed criteria carry `ApiRoutes` (`SAIFDictionary(Of IApiRoute)`) and a `GetApiClient`/`FormatRoute` mechanism instead of SQL text. REST plumbing (`ApiClient`/`IApiClient`, `ApiRequest`/`IApiRequest`, `ApiResult`/`IApiResult`, `clsDataApiAccess`/`IDataApiAccess`) is built on the `RestSharp` package and reached via `IDataPortalInfo.ApiClients`/`DataApiAccessLayer`.
- **Data access layer (V1\DataAccessLayer)**: `IDataAccess`/`clsDataAccess` is the central data-access registry managing multiple `IDataPortal` instances keyed by `PortalID`. `IDataPortalInfo`/`clsDataPortalInfo` is the central "DPI" object passed to every business object, exposing `ProcessPortalRequest`, `ExecuteScalar`, `GetResultSet`, `GetNextSeqNum`, `GetXML`, `NewPortalRequest`, `ApiClients`, and `DataApiAccessLayer`. `IDataLayer` is the abstraction implemented by both `clsMSOracleDataLayer` (Oracle, via `Oracle.ManagedDataAccess`, sets `DBMSType = clsDataAccess.clsEnvironment.DBMS.Oracle`) and `clsSQLDataLayer` (SQL Server), each with parallel driver-specific `IDataPortal`/`IDataRequest`/`IPortalRequest` implementations (`clsMSOracleDataPortal`/`MSOracleDataRequest`/`MSOraclePortalRequest` vs. `SQLDataPortal`/`SQLDataRequest`/`SQLPortalRequest`). The `DataPortalType` enum (`MSOracle`, `Oracle`, `SQLServer`, `ActiveDirectory`, `Api`, `ApiAndDb`) confirms multi-source targeting, including the API/DB hybrid, is a first-class design goal.*
- **Business rules engine (V1\BusinessRules and V2\BusinessRules)**: V1's `clsRulesManager` stores and invokes rule-handler delegates and tracks results (`clsRule`, `clsRuleArgs`, `clsRuleAttributes`, `clsRuleCollection`, `clsRuleInformation`, `clsBrokenRule`/`clsBrokenRuleCollection`, `clsBrokenRuleResult`/`clsBrokenRuleResultManager`/`clsBrokenRuleResultReason`). V2 provides a modernized, non-Hungarian-prefixed rework of the same concepts (`RuleManager`, `BusinessRule`, `BrokenRule`, `BrokenRuleCollection`, `BusinessRuleCollection`, `BusinessRuleInformation`, `RuleArgs`) coexisting in the same assembly.
- **Smart value types (V1\SmartValues and V2\SmartValues)**: V1 supplies `clsSmartString`, `clsSmartDecimal`, `clsSmartDate`, `clsSmartProperty` as DB-null-safe property wrappers. V2 supplies a modernized parallel set (`SmartValue`, `SmartString`, `SmartDate`, `SmartDecimal`, `SmartInteger`, `ISmartValue`).
- **Supporting infrastructure**: `clsUndoableBase`/`clsSortableCollectionBase` provide the undo and sortable-collection mechanics beneath the business-object layer; `TrackedProperty`/`TrackedProperties`/`ITrackedProperty` (and API counterparts `TrackedApiProperty`/`TrackedApiProperties`) provide property-change tracking; `clsCodeTableBase`/`clsCodeCollection`/`clsCodeItem`/`clsCodeDescription` provide code-table/lookup abstractions; `clsReportSpecification`/`clsReportXMLBuilder`/`SAIFXDocument`/`SAIFXElement`/`ReportableAttribute` (V1) and `clsErrorCodes`/`CustomXmlSerializer` (V2) provide XML/report-building utilities.

## Interaction model
- Every `clsBusinessBase`-derived business object owns a `clsRulesManager` (`Rules` property) used to enforce business rules via `Rules.CheckRules("RuleName")`, typically invoked from a property setter.*
- Business objects reach the database exclusively through the DPI (`IDataPortalInfo`/`clsDataPortalInfo`), which delegates to `IDataAccess.ProcessPortalRequest`; this decouples business-object code from the concrete Oracle or SQL Server driver in use.
- For API-backed business objects, `clsBusinessApiCriteriaBase.GetApiClient`/`FormatRoute` resolves a named `IApiClient` from the DPI (`IDataPortalInfo.ApiClients`) and formats a configured `IApiRoute` template with call-site arguments, in place of executing SQL.
- `clsUndoableBase` (base of `clsBusinessBase`) and `clsSortableCollectionBase` (base of `clsBusinessCollectionBase`) provide n-level undo (`BeginEdit`/`CancelEdit`/`ApplyEdit`) beneath the business-object layer, supporting UI edit/cancel scenarios.
- Broken-rule state raised by the rules engine surfaces to UI consumers via `IDataErrorInfo.Error`/`Item`, implemented on both `clsBusinessBase` and `clsBusinessCollectionBase`.
- `clsRetrieveOnlyBusinessCriteria` enforces, at the framework level, that mutating operations (Create/Insert/Update/Delete) are unsupported for read-only business objects, by throwing `ApplicationException("SQL property not available.")` if those properties are accessed.
- `ISerializationNotification` (`Deserialized`/`Serialized`/`Serializing`), implemented on both `clsBusinessBase` and `clsBusinessCollectionBase`, provides hooks for custom logic around binary/remoting serialization.

## Architecture diagram
The following diagram shows the dual business-object hierarchies converging on the shared data-portal abstraction, and the V1/V2 rules engine coexistence.

```mermaid
flowchart TD
	BB[clsBusinessBase<br>+ clsBusinessCollectionBase] --> RM1[clsRulesManager V1]
	AB[clsBusinessApiBase<br>+ clsBusinessCollectionApiBase] --> CB[clsBusinessApiCriteriaBase]
	BB --> CRIT[clsBusinessCriteriaBase /<br>clsRetrieveOnlyBusinessCriteria]
	CRIT --> DPI[IDataPortalInfo / clsDataPortalInfo]
	CB --> DPI
	DPI --> DAL[IDataAccess / clsDataAccess]
	DAL --> ORA[clsMSOracleDataLayer<br>Oracle.ManagedDataAccess]
	DAL --> SQL[clsSQLDataLayer<br>SQL Server]
	DPI --> APICLIENT[ApiClient / IDataApiAccess<br>RestSharp]
	RM2[RuleManager V2] -.not wired into base classes.-> BB
```

## Sequence diagram
The following diagram shows the primary business-object save sequence, from rule enforcement through the data portal to the concrete database driver.

```mermaid
sequenceDiagram
	participant Consumer as Business object (clsBusinessBase subclass)
	participant Rules as clsRulesManager
	participant DPI as IDataPortalInfo
	participant DAL as IDataAccess
	participant Driver as IDataLayer (Oracle/SQL Server)
	Consumer->>Rules: CheckRules("RuleName")
	Rules-->>Consumer: Broken rules (if any)
	Consumer->>DPI: ProcessPortalRequest(criteria)
	DPI->>DAL: ProcessPortalRequest
	DAL->>Driver: Execute via IDataPortal/IDataRequest
	Driver-->>DAL: Result set / scalar / XML
	DAL-->>DPI: Result
	DPI-->>Consumer: Result
```

## Design constraints
- Core has outbound dependencies on sibling framework libraries (`SAIF.Framework.Security`, `SAIF.Framework.Connection`, `SAIF.Framework.Logging`, `SAIF.Framework.DNS`, `SAIF.Framework.Security.EnvironmentApi`, `SAIF.Framework.Bindable`) via project references and VB `Imports` — despite being the architectural base, Core is not a dependency-free leaf.*
- Two generations of the business rules engine (`clsRulesManager`/V1 and `RuleManager`/V2) and of smart value types (`clsSmartString`/etc. V1 and `SmartString`/etc. V2) coexist in the same assembly; no code within Core itself was observed wiring V2 rule or smart-value types into `clsBusinessBase`, so V1 remains the active base-class integration point (`clsBusinessBase.m_Rules As New clsRulesManager`).**
- The data-access abstraction (`IDataLayer`) is designed to support Oracle and SQL Server interchangeably, plus Active Directory and REST API sources, via the `DataPortalType` enum (`MSOracle`, `Oracle`, `SQLServer`, `ActiveDirectory`, `Api`, `ApiAndDb`); Core provides only the driver/portal plumbing, never domain-specific SQL statements (0 non-empty SQL properties across all `IBusinessCriteria` implementations in Core).
- `clsBusinessApiCriteriaBase`'s SQL properties are always empty by design — API-backed business objects must not use the SQL path; the `Api`/`ApiAndDb` `DataPortalType` values confirm this hybrid model is intentional rather than a stopgap.*
- Core defines no authentication/authorization enforcement logic of its own; `SAIF.Framework.Security` is imported as a namespace but no call site within Core was found invoking a security API from it during analysis.**
- Core does not itself consume `IEnvironmentService` or `ConfigurationManager.AppSettings`; its only configuration surface is the legacy VB "My Namespace" `ApplicationSettingsBase` pattern (one setting, the `SAIFDates` web-service URL) and the Oracle ODP.NET `oracle.manageddataaccess.client` config section.
- `SAIF.Framework.Core` is the primary/root project for the repository's single NuGet package pipeline (`SAIF.BOF.Framework`), and the packaged nuspec bundles compiled DLLs from referenced projects plus raw `.vb`/`.cs` source from every top-level library folder in the repository.

> **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.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Configuration](configuration.md)
- [API reference](api/index.md)

## Sources
- `SAIF.Framework.Core\V1\BaseItems\clsBusinessBase.vb`
- `SAIF.Framework.Core\V1\BaseItems\clsBusinessCollectionBase.vb`
- `SAIF.Framework.Core\V1\BaseItems\clsUndoableBase.vb`
- `SAIF.Framework.Core\V1\BaseItems\clsSortableCollectionBase.vb`
- `SAIF.Framework.Core\V1\BaseItems\clsBusinessCriteriaBase.vb`
- `SAIF.Framework.Core\V1\BaseItems\clsRetrieveOnlyBusinessCriteria.vb`
- `SAIF.Framework.Core\V1\Api\clsBusinessApiBase.vb`
- `SAIF.Framework.Core\V1\Api\clsBusinessCollectionApiBase.vb`
- `SAIF.Framework.Core\V1\Api\clsBusinessApiCriteriaBase.vb`
- `SAIF.Framework.Core\V1\Interfaces\iDataAccess.vb`
- `SAIF.Framework.Core\V1\DataAccessLayer\clsDataAccess.vb`
- `SAIF.Framework.Core\V1\Interfaces\iDataPortalInfo.vb`
- `SAIF.Framework.Core\V1\DataAccessLayer\clsDataPortalInfo.vb`
- `SAIF.Framework.Core\V1\Interfaces\iDataPortal.vb`
- `SAIF.Framework.Core\V1\Interfaces\iDataRequest.vb`
- `SAIF.Framework.Core\V1\Interfaces\iPortalRequest.vb`
- `SAIF.Framework.Core\V1\Interfaces\IDataLayer.vb`
- `SAIF.Framework.Core\V1\DataAccessLayer\MSOracle\MSOracleDataLayer.vb`
- `SAIF.Framework.Core\V1\DataAccessLayer\SQLServer\SQLDataLayer.vb`
- `SAIF.Framework.Core\V1\DataAccessLayer\DataAccessEnums.vb`
- `SAIF.Framework.Core\V1\BusinessRules\clsRulesManager.vb`
- `SAIF.Framework.Core\V2\BusinessRules\` (RuleManager and related types)
- `SAIF.Framework.Core\V1\SmartValues\` (clsSmartString, clsSmartDecimal, clsSmartDate, clsSmartProperty)
- `SAIF.Framework.Core\V2\SmartValues\` (SmartValue, SmartString, SmartDate, SmartDecimal, SmartInteger, ISmartValue)
- `SAIF.Framework.Core\SAIF.BOF.Framework.Core.vbproj`
- `SAIF.Framework.Core\SAIF.BOF.Framework.Core.nuspec`
- `SAIF.Framework.Core\app.config`
- `Pipelines\build-vars.yml`
