Source of truth (2026)
  • DataManagementEngineStandard/Editor/UOW/UnitOfWorkWrapper.cs (1164 lines)

Overview

UnitOfWorkWrapper provides a strongly-typed interface around dynamically-created UnitOfWork instances. It implements both IUnitOfWorkWrapper and IUnitofWork interfaces with:

  • Safe property access - All property get/set operations are wrapped in try-catch
  • Event forwarding - Forwards events from underlying UnitOfWork via reflection
  • Oracle Forms compatibility - Navigation methods (MoveFirst, MoveNext, etc.)
  • Validation support - Integration with validation framework
  • Undo/Redo - Full undo/redo capability
  • Virtual loading - Support for large datasets with paging

Properties

PropertyTypeDescription
IsInListModeboolGets/sets whether the UOW is in list mode
IsDirtyboolTrue if there are unsaved changes
DataSourceIDataSourceThe underlying data source
DatasourceNamestringName of the data source
EntityNamestringName of the entity/table
EntityTypeTypeThe entity CLR type
PrimaryKeystringPrimary key field name
GuidKeystringGUID key field name (if applicable)
UnitsdynamicThe collection of entities
CurrentItemdynamicCurrent record (Oracle Forms compatible)
CurrentIndexintCurrent position (Oracle Forms compatible)
CountintTotal record count
PageIndexintCurrent page index
PageSizeintRecords per page (default: 10)
InsertedKeysDictionary<int,string>Keys of inserted records
UpdatedKeysDictionary<int,string>Keys of updated records
DeletedKeysDictionary<int,string>Keys of deleted records
DeletedUnitsList<dynamic>Deleted entity instances
CommitOrderCommitOrderOrder of operations during commit (DeletesFirst, InsertsFirst, AsTracked)
IsIdentityboolWhether primary key is auto-increment
IsLoggingboolEnable operation logging
UpdateLogDictionary<DateTime,EntityUpdateInsertLog>Audit log of changes

Events

All events are forwarded from the underlying UnitOfWork via reflection:

EventArgsDescription
CurrentChangedEventHandlerCurrent record changed
ItemChangedItemChangedEventArgs<Entity>Item property changed
PreDeleteUnitofWorkParamsBefore delete
PreInsertUnitofWorkParamsBefore insert
PreCreateUnitofWorkParamsBefore create
PreUpdateUnitofWorkParamsBefore update
PreQueryUnitofWorkParamsBefore query
PostQueryUnitofWorkParamsAfter query
PostInsertUnitofWorkParamsAfter insert
PostCreateUnitofWorkParamsAfter create
PostUpdateUnitofWorkParamsAfter update
PostDeleteUnitofWorkParamsAfter delete
PreCommitUnitofWorkParamsBefore commit
PostCommitUnitofWorkParamsAfter commit

CRUD Operations

Async Operations (Preferred)

MethodSignatureDescription
UpdateAsyncTask<IErrorsInfo>(dynamic doc)Update entity asynchronously
InsertAsyncTask<IErrorsInfo>(dynamic doc)Insert entity asynchronously
DeleteAsyncTask<IErrorsInfo>(dynamic doc)Delete entity asynchronously
InsertDocTask<IErrorsInfo>(dynamic doc)Insert document
UpdateDocTask<IErrorsInfo>(dynamic doc)Update document
DeleteDocTask<IErrorsInfo>(dynamic doc)Delete document

Sync Operations (Legacy)

MethodSignatureDescription
Newvoid()Create new empty entity
Createvoid(dynamic entity)Create entity
Addvoid(dynamic entity)Add entity to collection
UpdateErrorsInfo(dynamic entity)Update entity
UpdateErrorsInfo(string id, dynamic entity)Update by ID
DeleteErrorsInfo()Delete current
DeleteErrorsInfo(string id)Delete by ID
DeleteErrorsInfo(dynamic doc)Delete entity
DeleteErrorsInfo(Func<dynamic,bool>)Delete by predicate
UpdateErrorsInfo(Func<dynamic,bool>, dynamic)Update by predicate

Batch Operations

MethodSignatureDescription
AddRangeTask<IErrorsInfo>(IEnumerable<dynamic>)Add multiple entities
UpdateRangeTask<IErrorsInfo>(IEnumerable<dynamic>)Update multiple entities
DeleteRangeTask<IErrorsInfo>(IEnumerable<dynamic>)Delete multiple entities

Transaction Operations

MethodSignatureDescription
CommitTask<IErrorsInfo>()Commit all changes
CommitTask<IErrorsInfo>(IProgress<PassedArgs>, CancellationToken)Commit with progress
CommitBatchAsyncTask<CommitBatchResult>(int, IProgress, CancellationToken)Batch commit
RollbackTask<IErrorsInfo>()Rollback all changes

Validation

Method/PropertyDescription
IsAutoValidateEnabledEnable automatic validation
BlockCommitOnValidationErrorPrevent commit if validation fails
ValidateItem(dynamic)Validate single item
ValidateAll()Validate all items
GetErrors(dynamic)Get validation errors for item
GetInvalidItems()Get all invalid items

Undo/Redo

Method/PropertyDescription
IsUndoEnabledEnable undo system
MaxUndoDepthMaximum undo history (default: 100)
CanUndoCan undo
CanRedoCan redo
Undo()Undo last operation
Redo()Redo last undone operation
ClearUndoHistory()Clear undo history

Virtual/Lazy Loading

Method/PropertyDescription
IsVirtualModeVirtual mode enabled
PageCacheSizePages to cache (default: 3)
VirtualTotalPagesTotal page count
EnableVirtualMode(int)Enable with total count
DisableVirtualMode()Disable virtual mode
GoToPageAsync(int)Navigate to page
PrefetchAdjacentPagesAsync()Preload adjacent pages
InvalidatePageCache()Clear page cache

Aggregates

MethodSignatureDescription
Sumdecimal(string propertyName)Sum of property values
SumWheredecimal(string, Func<dynamic,bool>)Conditional sum
Averagedecimal(string)Average of property values
AverageWheredecimal(string, Func<dynamic,bool>)Conditional average
Minobject(string)Minimum value
Maxobject(string)Maximum value
CountWhereint(Func<dynamic,bool>)Count matching records
DistinctValuesList<object>(string)Distinct values
GroupByDictionary<object,List<dynamic>>(string)Group by property

Batch Operations

// Batch update with progress
var result = await wrapper.CommitBatchAsync(
    batchSize: 100,
    progress: new Progress<CommitBatchProgress>(p => 
        Console.WriteLine($"Batch {p.CurrentBatch}/{p.TotalBatches}")),
    ct: cancellationToken);

Error Handling

All operations are wrapped in safe execution helpers:

  • GetPropertySafely - Returns default value on error
  • SetPropertySafely - Throws on error (setter failures are critical)
  • ExecuteSafely - Returns default value on error
  • ExecuteSafelyAsync - Returns default value on async error

ObjectDisposedException is thrown if wrapper is used after Dispose().

Usage Examples

Basic CRUD

var wrapper = UnitOfWorkFactory.CreateUnitOfWork(
    typeof(Customer), editor, "MyDb", "Customers", "Id");

// Add
wrapper.New();
wrapper.CurrentItem.Name = "John";
await wrapper.InsertAsync(wrapper.CurrentItem);

// Update
wrapper.MoveFirst();
wrapper.CurrentItem.Name = "Jane";
await wrapper.UpdateAsync(wrapper.CurrentItem);

// Commit
var result = await wrapper.Commit();
if (result.Flag == Errors.Ok)
    Console.WriteLine("Success");

Navigation with Events

wrapper.CurrentChanged += (s, e) => 
    Console.WriteLine($"Current: {wrapper.CurrentIndex}");

wrapper.PreCommit += (s, e) =>
{
    if (wrapper.GetInvalidItems().Any())
        e.Cancel = true;
};

wrapper.MoveFirst();
while (!wrapper.IsAtLast)
{
    Console.WriteLine(wrapper.CurrentItem.Name);
    wrapper.MoveNext();
}

Validation

wrapper.IsAutoValidateEnabled = true;
wrapper.BlockCommitOnValidationError = true;

var validation = wrapper.ValidateAll();
if (!validation.IsValid)
{
    foreach (var error in validation.Errors)
        Console.WriteLine(error.Message);
}