AAurora Workflows
Get started
Documentation

Data Context

Typed variable store shared across all tasks in a workflow execution

What Is the Data Context?

The Data Context (IWorkflowDataContext) is the communication backbone of every Aurora workflow execution. Each task receives the same context instance (or a child derived from it) and uses it to read inputs and write outputs. It acts as a strongly-typed, key-value dictionary keyed by .NET type and an optional custom string key.

Creating a Context

var context = WorkflowDataContext.Create(workflow);

// Pre-populate variables before starting:
context["myKey"] = "some value";
context[typeof(int)] = 42;

Core API

Method / PropertyDescription
this[string key]Get or set a value by raw string key.
this[Type type]Get or set a value by .NET type (uses the type's full name as key).
void Set(object value, string customKey)Store a value. If customKey is omitted the type name is used.
T Get<T>(string customKey)Retrieve a typed value. Returns the default if not found.
object Get(Type type, string customKey)Retrieve an untyped value by type.
object Get(string customKey)Retrieve an untyped value by raw key.
T GetOrCreate<T>(string tag, string customKey)Returns the stored value or creates and stores a new instance via the default constructor.
T TryGet<T>(string customKey)Like Get<T> but returns default(T) instead of throwing when not found.
bool Has<T>(string customKey)Returns true if a value for that type/key exists in the store.
IDictionary<string, object> GetAll()Returns a detached snapshot of all stored key-value pairs. Modifying the returned dictionary does not affect the context.
void Clear()Removes all stored values.
void MergeFrom(IWorkflowDataContext)Copies all entries from another context into this one (last-write wins).
IWorkflowDataContext Clone()Creates a shallow copy: entries are copied, the stored values themselves are shared.
Guid SessionIdentifierIdentifies the current execution session. Shared across all tasks in one run.
Guid IdUnique identity of this specific context instance.
IWorkflow WorkflowReference back to the owning workflow.
Thread safety. All members are safe to call concurrently from multiple tasks. GetOrCreate<T> is atomic, so parallel tasks never observe two different instances for the same key.

Scope-Aware Access: ScopedDataAccessor

The raw context is intentionally simple. All task-level semantics – custom input/output variable names, the __LASTOUTPUT marker and parent/global scope selection – live in ScopedDataAccessor. Tasks use it implicitly through GetInput<T>(context) / SetOutput(context, value), but hosting code, tests and tooling can obtain the same behaviour for any object implementing IVariableScopeSettings (every task does):

// Read/write exactly as the task itself would
var data = context.For(task);

data.SetOutput("result", 42);          // honours CustomOutputVariableName, scope flags and __LASTOUTPUT
var value = data.GetInput<int>("result");
var previous = data.GetPreviousTaskOutput();

// Resolve the effective scopes
IWorkflowDataContext inputScope  = data.GetInputScope();
IWorkflowDataContext outputScope = data.GetOutputScope();
IWorkflowDataContext global      = data.GetGlobalVariableSpace(); // falls back to the local context when no global scope is injected
MemberDescription
GetInput<T>(name) / GetInput(name)Custom input variable first, then the named variable (defaults to the type name), then __LASTOUTPUT if it is assignable to T.
SetOutput(name, value)Writes to the effective output scope. In the local scope the value is also stored under its type name and as __LASTOUTPUT; parent/global writes do not touch __LASTOUTPUT to keep parallel tasks independent.
GetPreviousTaskOutput()Reads __LASTOUTPUT from the effective input scope.
GetVariableScope(), GetInputScope(), GetOutputScope()Resolve the default, input and output scopes from the task's Use* flags. Parent takes precedence over global; a missing parent scope falls back to global/local.
SetErrorState(exception, taskName) / ClearErrorFlag()Maintain the __ERROROCCURED flag and the EX_<taskName> entry used by ContinueOnError.

Well-known keys are exposed as constants in WorkflowDataContextKeys (LastOutput, ErrorOccured, GlobalVariable, ParentScopeVariable).

Scope Inheritance

Scope tasks (ForEachTask, LoopTask, ConditionalScope, etc.) create a child context for the tasks they contain. By default, child tasks read from and write to this local scope. Use the following task properties to control scoping:

  • UseGlobalScopeForInput – the task reads its input from the top-level workflow context.
  • UseGlobalScopeForOutput – the task writes its output to the top-level workflow context.
  • UseParentScopeForInput – the task reads from the direct parent scope.
  • UseParentScopeForOutput – the task writes to the direct parent scope.

Using Variables in Expressions (Property Fields Only)

Task code vs. expressions: inside task implementations (DoAsync etc.) use GetInput<T>(context), SetOutput(context, value) and Resolve<T>(property, context) (or context.For(this) for the full scope-aware accessor). Direct access bypasses scope resolution and variable name configuration and will cause incorrect behaviour.

Inside a = prefixed expression, every variable that is visible in the current scope is injected as a typed C# local with its variable name. Variables of the global scope are additionally available as _global_<name>, variables of the direct parent scope as _parent_<name>. The raw dictionary is available as DataContext. Examples:

// Read a string variable named "fileName"
=fileName.ToUpper()

// Compute from two variables
=width * height

// Global variable from inside a nested scope (e.g. a loop body)
=Path.Combine(_global_baseDir, fileName)

// Check presence via the raw dictionary
=DataContext.ContainsKey("apiKey") ? (string) DataContext["apiKey"] : "default"

Pre-populating Variables (CLI / Hosting)

Before calling StartAsync, populate the context with any values that tasks should see as inputs:

var context = WorkflowDataContext.Create(workflow);
context["inputFile"]  = @"C:\data\report.csv";
context["maxRows"]    = 1000;
context["dryRun"]     = true;

await workflow.StartAsync(context);

The CLI Runner does this automatically by mapping --key value command-line arguments to string entries in the context.

Core APIScope-Aware AccessScope Inheritance