Overview

DataImportManager (namespace TheTechIdea.Beep.Editor.Importing) is a partial-class orchestrator that moves data between any two IDataSource instances. It supports the full ETL lifecycle: schema compatibility checks, field-level quality rules, multi-phase transformation pipelines, intelligent batch processing, incremental sync, schema drift detection, staging tables, error quarantine, dead-letter replay, and run-history persistence.

DataImportManager (main + partial classes)
├── DataImportManager.Core.cs        ← data-source init, entity discovery
├── DataImportManager.Migration.cs   ← preflight validation, sync-draft
└── DataImportManager.Replay.cs      ← dead-letter replay

Helpers (injected / created internally)
├── IDataImportValidationHelper      ← config and compatibility checks
├── IDataImportTransformationHelper  ← field filter · mapping · defaults · custom fn
├── IDataImportBatchHelper           ← optimal sizing, batch splitting, retry
└── IDataImportProgressHelper        ← logging, progress, metrics

Supporting subsystems
├── Quality/          IDataQualityRule, BuiltInRules (NotNull, Unique, Range, Regex, …)
├── ErrorStore/       IImportErrorStore + ImportErrorRecord
├── History/          IImportRunHistoryStore + ImportRunRecord
├── Staging/          StagingOptions
├── Schema/           SchemaComparator, SchemaSnapshot
└── Profiling/        DataProfiler, DataProfile, FieldProfile

Quick Start

Minimal import (backward-compatible)

using var mgr = new DataImportManager(dmeEditor);

mgr.SourceDataSourceName = "ExternalCRM";
mgr.SourceEntityName     = "Contacts";
mgr.DestDataSourceName   = "MainDB";
mgr.DestEntityName       = "Customers";

var progress = new Progress<IPassedArgs>(a => Console.WriteLine(a.Messege));
using var cts = new CancellationTokenSource();

var result = await mgr.RunImportAsync(progress, cts.Token, null, batchSize: 100);
Console.WriteLine(result.Flag); // Errors.Ok | Errors.Failed

ImportContext entry point (recommended)

var ctx = new ImportContext
{
    Selection = new ImportSelectionContext
    {
        SourceDataSourceName      = "ExternalCRM",
        SourceEntityName          = "Contacts",
        DestinationDataSourceName = "MainDB",
        DestinationEntityName     = "Customers"
    },
    Options = new ImportExecutionOptions
    {
        BatchSize             = 200,
        RunMigrationPreflight = true,
        OnBatchError          = BatchErrorStrategy.Skip
    }
};

using var mgr = new DataImportManager(dmeEditor);
var result = await mgr.RunImportAsync(ctx, progress, CancellationToken.None);

ImportContext

ImportContext is the canonical, serialisable entry-point for all import runs. It replaces the older string-key parameter dictionary.

ImportContext

PropertyTypeDescription
RunIdstringAuto-generated GUID for this run (used for correlation in logs and error store)
SelectionImportSelectionContextSource + destination identifiers
MappingEntityDataMap?Optional field-level mapping; null = use same field names
OptionsImportExecutionOptionsExecution knobs (batch size, preflight, retry, …)

ImportSelectionContext

PropertyDefaultDescription
SourceDataSourceNameRegistered name of the source IDataSource
SourceEntityNameEntity / table to read from
DestinationDataSourceNameRegistered name of the destination IDataSource
DestinationEntityNameEntity / table to write to
CreateDestinationIfNotExiststrueAuto-create missing entity on destination
IsValidcomputedReturns true only when all four identifiers are non-empty

ImportExecutionOptions

PropertyDefaultDescription
BatchSize100Records per write batch
OnBatchErrorBatchErrorStrategy.SkipWhat to do when a batch fails: Abort, Skip, or Retry
MaxRetries3Max retry attempts before applying OnBatchError
RunMigrationPreflightfalseRun schema-compatibility check before starting the import
AddMissingColumnstrueAutomatically add source columns missing from destination
CreateSyncProfileDraftfalseGenerate a DataSyncSchema draft after preflight but before executing
RunImportOnFinishtrueExecute the actual import after preflight / draft generation

BatchErrorStrategy enum

ValueBehaviour
AbortStop the entire import on first batch failure
SkipLog the failure, quarantine the batch, continue
RetryRetry up to MaxRetries times before quarantining

DataImportConfiguration

DataImportConfiguration is the expanded configuration object used when callers need fine-grained control. It is accepted by RunImportAsync(config, …) and can be built from an ImportContext via BuildConfigurationFromContext(ctx).

Core identifiers

PropertyTypeDescription
SourceEntityNamestringSource entity / table name
DestEntityNamestringDestination entity / table name
SourceDataSourceNamestringRegistered source datasource name
DestDataSourceNamestringRegistered destination datasource name
SourceDataIDataSourceResolved source; auto-populated if name is set
DestDataIDataSourceResolved destination; auto-populated if name is set

Data shaping

PropertyDefaultDescription
MappingnullField-level EntityDataMap; null = identity mapping
SourceFilters[]List of AppFilters applied when reading source data
SelectedFieldsnullColumn whitelist; null = include all fields
CustomTransformationnullFunc<object, object> applied per-record after mapping

Defaults & batching

PropertyDefaultDescription
DefaultValues[]Static defaults; auto-loaded from DefaultsManager when ApplyDefaults=true
ApplyDefaultstrueLoad + apply DefaultsManager defaults during transformation
BatchSize50Number of records per write batch
SkipBlanksfalseSkip records that are entirely blank / null
CreateDestinationIfNotExiststrueAuto-create missing destination entity

Advanced pipeline phases

PropertyPhaseDefaultDescription
RunMigrationPreflight3falseRun schema preflight before import
AddMissingColumns3trueAuto-add source columns absent from destination
CreateSyncProfileDraft3falseBuild sync-draft without executing
OnBatchError1SkipBatch failure strategy
MaxRetries13Max retries per batch
SyncMode6FullRefreshFull refresh, incremental, or upsert
WatermarkColumn6""Column used for incremental watermark tracking
LastWatermarkValue6nullLast seen watermark value; reads newer records only
UpsertKeyColumns6[]Key columns used for upsert matching
QualityRules7[]Per-record data quality rules
DriftPolicy8AutoAddColumnsHow to handle schema drift between runs
ErrorStore9nullPluggable error/quarantine store
RunHistoryStore10nullPluggable run-history persistence
Staging11nullOptional two-phase staging options

Run API

MethodDescription
RunImportAsync(ImportContext, IProgress<IPassedArgs>, CancellationToken) Recommended entry point. Builds config from context and executes the full pipeline.
RunImportAsync(DataImportConfiguration, IProgress<IPassedArgs>, CancellationToken) Accepts an explicit config object for callers that need fine-grained control.
RunImportAsync(IProgress, CancellationToken, EntityDataMap, int batchSize) Legacy backward-compatible overload; reads properties set on the manager directly.
BuildConfigurationFromContext(ImportContext) Translates an ImportContext to a DataImportConfiguration without executing.
CreateImportConfiguration(src, srcDS, dest, destDS) Factory helper — creates a ready-to-run config from the four core string identifiers.
TestImportConfigurationAsync(DataImportConfiguration) Validates connectivity and entity presence without importing any records.
ReplayFailedRecordsAsync(contextKey, progress, token) Replays pending dead-letter records from the error store for a given context key.

Return value

All async methods return Task<IErrorsInfo>:

PropertyTypeDescription
FlagErrorsErrors.Ok on success, Errors.Failed on failure
MessagestringHuman-readable status or error message
ExException?Caught exception, if any

Lifecycle Control

Imports run asynchronously. The manager exposes pause / resume / cancel controls that are safe to call from any thread.

Method / EventDescription
PauseImport()Signals the running import to pause at the next batch boundary. State → Paused.
ResumeImport()Releases the pause gate. State → Running.
CancelImport()Triggers cancellation. State → Cancelled. Already-committed batches are kept.
GetImportStatus()Returns a thread-safe detached ImportStatus snapshot. Safe to poll from UI thread.

ImportState enum

ValueDescription
IdleNo import running
RunningImport actively processing batches
PausedImport suspended at batch boundary
CompletedImport finished successfully
FaultedImport terminated by unhandled error
CancelledImport stopped via CancelImport()

ImportStatus

GetImportStatus() returns a snapshot — mutations do not affect the live state.

PropertyTypeDescription
StateImportStateCurrent lifecycle state
RecordsProcessedintRecords written to destination so far
TotalRecordsintTotal records to process (0 if unknown)
PercentCompletedouble0–100
LastMessagestringMost recent log message
StartedAtDateTime?UTC start time
FinishedAtDateTime?UTC finish time (null while running)
RecordsBlockedintRecords rejected by quality rules (Block action)
RecordsQuarantinedintRecords sent to error store (Quarantine action)
RecordsWarnedintRecords written with a quality warning (Warn action)
MetricsImportPerformanceMetrics?Per-run throughput metrics
IsRunning / IsPaused / IsCompleted / IsCancelled / HasErrorsboolConvenience flags

ImportPerformanceMetrics

PropertyTypeDescription
ElapsedTimeTimeSpanTime since import started
RecordsPerSeconddoubleThroughput
EstimatedTimeRemainingTimeSpanETA based on current throughput
PercentageCompletedouble0–100
RecordsProcessed / TotalRecordsintSnapshot counts
LastUpdatedDateTimeWhen metrics were last computed

Migration Preflight

Preflight validation checks schema compatibility without writing any records. Enable it via ImportExecutionOptions.RunMigrationPreflight = true or call it directly.

// Direct call (independent of a full RunImportAsync)
var result = await mgr.RunMigrationPreflightAsync(config, log: msg => Console.WriteLine(msg));
if (result.Flag == Errors.Failed)
{
    Console.WriteLine($"Preflight failed: {result.Message}");
    return;
}

// Build sync-draft schema (no records imported)
var draft = await mgr.BuildSyncDraftAsync(config);

Preflight checks performed

  1. Source datasource resolves and is connected.
  2. Destination datasource resolves and is connected.
  3. Source entity structure can be read.
  4. Destination entity exists (or will be created if CreateDestinationIfNotExists=true).
  5. When AddMissingColumns=false: all source fields must already exist on the destination.

Data Quality Rules

Add IDataQualityRule instances to DataImportConfiguration.QualityRules. Each rule is evaluated per-record before writing. Failures trigger the rule's OnFailure action.

DataQualityAction enum

ValueBehaviour
BlockReject the record — do not write, increment RecordsBlocked
QuarantineSend the record to the error store for later replay, increment RecordsQuarantined
WarnWrite the record but log a warning, increment RecordsWarned

Built-in rules

Rule classConstructorWhat it checks
NotNullRule(fieldName, onFailure)Value must be non-null and non-empty
UniqueRule(fieldName, onFailure)All values within a batch must be distinct (case-insensitive)
RangeRule(fieldName, min, max, onFailure)Numeric / date value must fall within [min, max]
RegexRule(fieldName, pattern, onFailure, options)String value must match the regex pattern
config.QualityRules.Add(new NotNullRule("CustomerID", DataQualityAction.Block));
config.QualityRules.Add(new UniqueRule("CustomerID", DataQualityAction.Quarantine));
config.QualityRules.Add(new RangeRule("Age", min: 0, max: 150, DataQualityAction.Block));
config.QualityRules.Add(new RegexRule("Email", @"^[^@]+@[^@]+\.[^@]+$", DataQualityAction.Warn));

// Custom rule
public class PositivePriceRule : IDataQualityRule
{
    public string FieldName  => "Price";
    public string RuleName   => "positive_price";
    public DataQualityAction OnFailure => DataQualityAction.Block;

    public bool Evaluate(object? value, object record) =>
        value != null && decimal.TryParse(value.ToString(), out var d) && d > 0;

    public string FailureMessage(object? value) =>
        $"Price must be positive (got '{value}').";
}

config.QualityRules.Add(new PositivePriceRule());

Schema Drift

The SchemaDriftPolicy controls what happens when the source entity's schema changes between runs. SchemaComparator (static utility) compares two SchemaSnapshot instances and produces a SchemaDriftReport.

SchemaDriftPolicy enum

ValueBehaviour
IgnoreProceed without checking for drift
AbortOnDriftAbort the import if any added, removed, or altered fields are detected
AutoAddColumns(Default) Automatically add new source columns to the destination
AutoDropColumnsRemove destination columns that no longer exist in source
config.DriftPolicy = SchemaDriftPolicy.AutoAddColumns;

// Manual schema comparison
var baseline = SchemaSnapshot.CaptureFrom(config.SourceData, config.SourceEntityName);
var current  = SchemaSnapshot.CaptureFrom(config.SourceData, config.SourceEntityName);
var report   = SchemaComparator.Compare(baseline, current);

Console.WriteLine($"Added:   {report.AddedFields.Count}");
Console.WriteLine($"Removed: {report.RemovedFields.Count}");
Console.WriteLine($"Altered: {report.AlteredFields.Count}");

Staging

When StagingOptions.Enabled = true, raw records are written to a staging entity (e.g. Customers_raw) first. The pipeline then normalizes and moves them to the final destination. Useful for auditing, validation gates, and multi-step transformations.

PropertyDefaultDescription
EnabledfalseMaster switch; false = direct import (no staging)
StagingEntitySuffix"_raw"Appended to entity name to form staging entity name (Customers_raw)
DropStagingAfterNormalizefalseDrop staging entity after successful normalization
SkipNormalizationfalseUseful for inspection-only runs — records stay in staging
config.Staging = new StagingOptions
{
    Enabled                   = true,
    StagingEntitySuffix       = "_staging",
    DropStagingAfterNormalize = false, // keep for audit
    SkipNormalization         = false
};

Error Store & Dead-Letter Replay

Assign an IImportErrorStore to config.ErrorStore to capture quarantined records. Two implementations ship out of the box:

IImportErrorStore API

MethodDescription
SaveAsync(record, token)Persist a single quarantined record
LoadAsync(contextKey, token)Return all error records for the given context key
LoadPendingAsync(contextKey, token)Return only records not yet replayed
MarkReplayedAsync(contextKey, batchNum, recIdx, token)Mark a record as successfully replayed
ClearAsync(contextKey, token)Delete all records for the context key

ImportErrorRecord

PropertyTypeDescription
ContextKeystringPipeline key: "{srcDS}/{srcEntity}/{destDS}/{destEntity}"
OccurredAtDateTimeUTC timestamp of the failure
BatchNumberintZero-based batch counter
RecordIndexintZero-based position within the batch
RuleNamestring?Quality rule that triggered the failure (if any)
ReasonstringHuman-readable failure description
RawRecordobject?The original faulted record (serialised as JSON)
Replayedbooltrue after a successful replay
ReplayedAtDateTime?UTC timestamp of successful replay
TriageNotestring?Optional notes added during manual triage

Dead-Letter Replay

// Attach error store to config
config.ErrorStore = new JsonFileImportErrorStore("./errors/");

var result = await mgr.RunImportAsync(config, progress, cts.Token);

// Later — replay records that previously failed
var contextKey = "ExternalCRM/Contacts/MainDB/Customers";
var replayResult = await mgr.ReplayFailedRecordsAsync(contextKey, progress, CancellationToken.None);
Console.WriteLine($"Replay: {replayResult.Flag}");

Data Profiling

DataProfiler (static utility) samples an entity and computes per-field statistics. Results are returned as a DataProfile containing a list of FieldProfile entries. Useful for understanding source data before configuring quality rules.

var profile = await DataProfiler.ProfileAsync(
    editor:         dmeEditor,
    dataSourceName: "ExternalCRM",
    entityName:     "Contacts",
    sampleSize:     2000,
    token:          CancellationToken.None);

foreach (var field in profile.Fields)
{
    Console.WriteLine($"{field.Name}: nulls={field.NullCount}, " +
                      $"distinct={field.DistinctCount}, " +
                      $"min={field.Min}, max={field.Max}");
}

DataProfile properties

PropertyDescription
DataSourceNameDatasource that was sampled
EntityNameEntity that was sampled
CapturedAtUTC timestamp of profiling
SampleSizeNumber of rows sampled
FieldsList of FieldProfile objects (one per column)

Run History

Assign an IImportRunHistoryStore to config.RunHistoryStore to persist run records. Two implementations ship: DataSourceImportRunHistoryStore and JsonFileImportRunHistoryStore.

IImportRunHistoryStore API

MethodDescription
SaveRunAsync(record, token)Persist a completed run record
GetRunsAsync(contextKey, token)Return all run records for the context key, newest first
GetLastSuccessfulRunAsync(contextKey, token)Return the most recent Completed run record, or null
ClearAsync(contextKey, token)Delete all run records for the context key

Incremental sync with watermarking

// Store and restore last watermark for incremental loads
var historyStore = new JsonFileImportRunHistoryStore("./history/");
config.RunHistoryStore = historyStore;

var last = await historyStore.GetLastSuccessfulRunAsync("CRM/Contacts/DB/Customers");
config.SyncMode          = SyncMode.Incremental;
config.WatermarkColumn   = "ModifiedDate";
config.LastWatermarkValue = last?.WatermarkValue; // null on first run = import all

var result = await mgr.RunImportAsync(config, progress, cts.Token);

Examples

Full pipeline with all features

using var mgr = new DataImportManager(dmeEditor);

var config = mgr.CreateImportConfiguration(
    "ProductFeed", "ExternalCatalog",
    "Products",   "MainDB");

// Field subset
config.SelectedFields = new List<string> { "SKU", "Name", "Price", "Stock" };

// Source filter — only changed in last 7 days
config.SourceFilters.Add(new AppFilter
{
    FieldName   = "ModifiedDate",
    Operator    = ">=",
    FilterValue = DateTime.Today.AddDays(-7).ToString("yyyy-MM-dd")
});

// Quality rules
config.QualityRules.Add(new NotNullRule("SKU",   DataQualityAction.Block));
config.QualityRules.Add(new NotNullRule("Name",  DataQualityAction.Quarantine));
config.QualityRules.Add(new RangeRule("Price", 0.01m, 999999m, DataQualityAction.Block));

// Error store — save quarantined records to JSON
config.ErrorStore = new JsonFileImportErrorStore("./errors/");

// Run history — enable incremental runs
config.RunHistoryStore = new JsonFileImportRunHistoryStore("./history/");
config.SyncMode        = SyncMode.Incremental;
config.WatermarkColumn = "ModifiedDate";

// Staging — write raw records first
config.Staging = new StagingOptions { Enabled = true, StagingEntitySuffix = "_raw" };

// Schema drift
config.DriftPolicy = SchemaDriftPolicy.AutoAddColumns;

// Business logic transformation
config.CustomTransformation = record =>
{
    if (record is Dictionary<string, object> d)
        d["ImportedAt"] = DateTime.UtcNow;
    return record;
};

// Execute
var progress = new Progress<IPassedArgs>(a => Console.WriteLine($"[{a.ParameterInt1}/{a.ParameterInt2}] {a.Messege}"));
var result   = await mgr.RunImportAsync(config, progress, CancellationToken.None);

// Check results
var status = mgr.GetImportStatus();
Console.WriteLine($"Result:      {result.Flag}");
Console.WriteLine($"Processed:   {status.RecordsProcessed}");
Console.WriteLine($"Quarantined: {status.RecordsQuarantined}");
Console.WriteLine($"Throughput:  {status.Metrics?.RecordsPerSecond:F1} rec/s");

Pause / Resume from UI

// Start import on background thread
_ = Task.Run(() => mgr.RunImportAsync(config, progress, cts.Token));

// Pause after 2 seconds (e.g., user clicks Pause button)
await Task.Delay(2000);
mgr.PauseImport();

var snap = mgr.GetImportStatus();
Console.WriteLine($"Paused at record {snap.RecordsProcessed}");

// Resume
await Task.Delay(3000);
mgr.ResumeImport();

Profile source data before import

var profile = await DataProfiler.ProfileAsync(dmeEditor, "ExternalCatalog", "ProductFeed", 5000);

// Log fields with >10% nulls — may need NotNullRule
foreach (var f in profile.Fields.Where(f => f.NullCount * 1.0 / profile.SampleSize > 0.1))
    Console.WriteLine($"High null rate: {f.Name} ({f.NullCount}/{profile.SampleSize})");

Full API Reference

IDataImportManager (complete interface)

MemberReturnDescription
ValidationHelperIDataImportValidationHelperRead-only accessor for the validation helper
TransformationHelperIDataImportTransformationHelperRead-only accessor for the transformation helper
BatchHelperIDataImportBatchHelperRead-only accessor for the batch helper
ProgressHelperIDataImportProgressHelperRead-only accessor for the progress helper
PauseImport()voidPause at next batch boundary. State → Paused
ResumeImport()voidRelease pause gate. State → Running
CancelImport()voidRequest cancellation. State → Cancelled
GetImportStatus()ImportStatusThread-safe detached status snapshot
RunImportAsync(ImportContext, IProgress, CancellationToken)Task<IErrorsInfo>Recommended entry point: context-based import
BuildConfigurationFromContext(ImportContext)DataImportConfigurationTranslates context to config without executing
CreateImportConfiguration(srcEntity, srcDS, destEntity, destDS)DataImportConfigurationFactory helper from four string identifiers
TestImportConfigurationAsync(DataImportConfiguration)Task<IErrorsInfo>Tests connectivity and entity presence
RunImportAsync(DataImportConfiguration, IProgress?, CancellationToken)Task<IErrorsInfo>Explicit config-based import
RunMigrationPreflightAsync(DataImportConfiguration, Action<string>?)Task<IErrorsInfo>Schema compatibility validation
BuildSyncDraftAsync(DataImportConfiguration)Task<DataSyncSchema>Build sync-draft schema without executing
ReplayFailedRecordsAsync(contextKey, IProgress?, CancellationToken)Task<IErrorsInfo>Dead-letter replay from error store

Helper Interfaces (all 4)

IDataImportValidationHelper

MethodReturn
ValidateImportConfiguration(DataImportConfiguration)IErrorsInfo
ValidateEntityMapping(EntityDataMap)IErrorsInfo
ValidateEntityCompatibility(EntityStructure, EntityStructure)IErrorsInfo
ValidateDataSources(IDataSource, IDataSource)IErrorsInfo

IDataImportTransformationHelper

MethodReturn
ApplyFieldFiltering(object, List<string>)object
ApplyEntityMapping(object, EntityDataMap, string)object
ApplyDefaultValues(object, List<DefaultValue>, EntityStructure, string)object
ApplyCustomTransformation(object, Func<object,object>)object
ApplyTransformationPipeline(object, DataImportConfiguration)object

IDataImportBatchHelper

MethodReturn
CalculateOptimalBatchSize(int, long, long?)int
ProcessBatchAsync(IEnumerable<object>, DataImportConfiguration, IProgress, CancellationToken)Task<IErrorsInfo>
SplitIntoBatches(IEnumerable<object>, int)IEnumerable<IEnumerable<object>>

IDataImportProgressHelper

MemberReturn/Params
ImportLogDataList<Importlogdata> {get;}
LogImport(string, int)void
LogError(string, Exception)void
ReportProgress(IProgress, string, int, int?)void
CalculatePerformanceMetrics(DateTime, int, int)ImportPerformanceMetrics
ClearLog()void

SchemaSnapshot & SchemaSnapshotStore

In Schema/: captures entity structure at a point in time for schema drift comparison.

// SchemaSnapshot — static capture method
public class SchemaSnapshot
{
    // Properties
    public string DataSourceName { get; set; }
    public string EntityName { get; set; }
    public DateTime CapturedAt { get; set; }
    public List<EntityField> Fields { get; set; }

    // Static factory
    public static SchemaSnapshot CaptureFrom(IDataSource ds, string entityName);
}

// SchemaComparator — static comparison utility
public static class SchemaComparator
{
    public static SchemaDriftReport Compare(SchemaSnapshot baseline, SchemaSnapshot current);
    // SchemaDriftReport: AddedFields, RemovedFields, AlteredFields lists
}

// SchemaSnapshotStore — persistence for schema snapshots
public class SchemaSnapshotStore
{
    public Task SaveSnapshotAsync(SchemaSnapshot snapshot);
    public Task<SchemaSnapshot?> LoadSnapshotAsync(string contextKey);
    public Task ClearAsync(string contextKey);
}

IWatermarkStore / WatermarkStore (incremental sync)

In Sync/: persists watermark values for incremental data imports.

public interface IWatermarkStore
{
    Task<object?> GetWatermarkAsync(string contextKey);
    Task SaveWatermarkAsync(string contextKey, object value);
    Task ClearAsync(string contextKey);
}

// Implementation
public class WatermarkStore : IWatermarkStore { /* backed by IDataSource or local store */ }

DataQualityEvaluator

In Quality/: orchestrates rule evaluation across a batch.

public class DataQualityEvaluator
{
    public DataQualityEvaluator(List<IDataQualityRule> rules, IImportErrorStore? errorStore = null);

    public QualityEvaluationResult Evaluate(object record);
    // Returns: Passed {bool}, Action {DataQualityAction}, Failures {List<RuleResult>}

    public class QualityEvaluationResult
    {
        public bool Passed { get; set; }
        public DataQualityAction Action { get; set; }
        public List<RuleResult> Failures { get; set; } = new();
    }

    public class RuleResult
    {
        public string RuleName { get; set; }
        public string FieldName { get; set; }
        public string Message { get; set; }
        public DataQualityAction Action { get; set; }
    }
}

LocalStoreFactory

In Factories/: creates local JSON-file backed error store, run history, and watermark stores.

public static class LocalStoreFactory
{
    public static IImportErrorStore CreateErrorStore(string directoryPath);
    public static IImportRunHistoryStore CreateRunHistoryStore(string directoryPath);
    public static IWatermarkStore CreateWatermarkStore(string directoryPath);
}

All Enums

EnumValues
ImportStateIdle, Running, Paused, Completed, Faulted, Cancelled
BatchErrorStrategyAbort, Skip, Retry
SyncModeFullRefresh, Incremental, Upsert
SchemaDriftPolicyIgnore, AbortOnDrift, AutoAddColumns, AutoDropColumns
DataQualityActionBlock, Quarantine, Warn
ImportLogLevelInfo, Warning, Error, Debug, Success

Source File Map

FileContent
DataImportManager.csMain class — fields, constructors, backward-compat properties, Dispose
DataImportManager.Core.csCore import pipeline — data-source init, entity discovery, main run loop
DataImportManager.Migration.csPreflight validation + sync-draft generation
DataImportManager.Replay.csDead-letter record replay from error store
Interfaces/IDataImportInterfaces.csAll interfaces + shared model types (ImportContext, ImportStatus, DataImportConfiguration, enums)
Helpers/DataImportValidationHelper.csValidation helper concrete implementation
Helpers/DataImportTransformationHelper.csTransformation pipeline (field filter → mapping → defaults → custom fn)
Helpers/DataImportBatchHelper.csBatch sizing, splitting, retry processing
Helpers/DataImportProgressHelper.csProgress reporting, logging, performance metrics
Factories/LocalStoreFactory.csCreates JSON-file backed stores (error, history, watermark)
Staging/StagingOptions.csStaging configuration (suffix, drop, skip normalization)
Schema/SchemaComparator.csBaseline vs current schema comparison → drift report
Schema/SchemaSnapshot.csPoint-in-time entity structure capture
Schema/SchemaSnapshotStore.csPersistence for schema snapshots
ErrorStore/IImportErrorStore.csError store contract
ErrorStore/ImportErrorRecord.csError record data class
ErrorStore/DataSourceImportErrorStore.csError store backed by IDataSource entity
ErrorStore/JsonFileImportErrorStore.csError store backed by JSON file
History/IImportRunHistoryStore.csRun history contract
History/ImportRunRecord.csRun record data class
History/DataSourceImportRunHistoryStore.csRun history backed by IDataSource
History/JsonFileImportRunHistoryStore.csRun history backed by JSON file
Profiling/DataProfiler.csAsync field-level profiling utility
Profiling/FieldProfile.csPer-field statistics (null count, distinct count, min, max)
Quality/IDataQualityRule.csQuality rule contract + DataQualityAction enum
Quality/BuiltInRules.csNotNullRule, UniqueRule, RangeRule, RegexRule
Quality/DataQualityEvaluator.csBatch rule evaluation orchestrator
Sync/IWatermarkStore.csWatermark persistence contract
Sync/WatermarkStore.csWatermark persistence implementation
Examples/DataImportManagerExamples.csUsage examples for the full pipeline