Table of Contents

Struct UpdateStep

Namespace
DynaSharp
Assembly
DynaSharp.dll

An update in a transaction: what can follow it are its changes and its condition, in any order, the verbs of the next action, and sending. One attribute can appear in one change of an update only. See TransactWriteExtensions for the rest.

public readonly ref struct UpdateStep : ITransactWriteStep<UpdateStep>, ITransactWriteChain<UpdateStep>, IConditional<UpdateStep>, IRetryable<UpdateStep>, IUpdatable<UpdateStep>
Implements
Inherited Members
Extension Methods

Remarks

Delete(string, AttributeValue) here removes elements from a set, which is the DELETE clause of the update. The verb of the next action takes a table, so the two do not mix.

An update of an entity with a discriminator gives a new item its type, and an item that exists keeps the one it has, as UpdateCommand<T> says.

Methods

Add(string, AttributeValue)

Adds to a number, or adds elements to a set (ADD). An attribute that does not exist starts from zero or the empty set.

public UpdateStep Add(string path, AttributeValue value)

Parameters

path string

The name or document path.

value AttributeValue

The number or the set.

Returns

UpdateStep

The command, which replaces this one.

Add<TNumber>(string, TNumber)

Adds to a number (ADD). An attribute that does not exist starts from zero. The token of the transaction makes a retry safe here, unlike in a single update.

public UpdateStep Add<TNumber>(string path, TNumber value) where TNumber : INumberBase<TNumber>

Parameters

path string

The name or document path.

value TNumber

The number, which may be negative.

Returns

UpdateStep

The step, which replaces this one.

Type Parameters

TNumber

The type of the number.

Add<TValue, TConverter>(Attr<TValue, NullableHandleConverter<TValue, TConverter>>, TValue)

Adds to a nullable number (ADD), see Add<TValue, TConverter>(Attr<TValue, TConverter>, TValue).

public UpdateStep Add<TValue, TConverter>(Attr<TValue, NullableHandleConverter<TValue, TConverter>> attribute, TValue value) where TValue : struct where TConverter : IDynamoDbConverter<TValue>, IAddableConverter

Parameters

attribute Attr<TValue, NullableHandleConverter<TValue, TConverter>>

The attribute.

value TValue

The number.

Returns

UpdateStep

The command, which replaces this one.

Type Parameters

TValue

The type of the attribute.

TConverter

The converter, of a number: ADD takes nothing else, so an attribute of another type is a compile error.

Add<TValue, TConverter>(Attr<TValue, NullableReferenceHandleConverter<TValue, TConverter>>, TValue)

Adds elements to a nullable set (ADD), see Add<TValue, TConverter>(Attr<TValue, TConverter>, TValue).

public UpdateStep Add<TValue, TConverter>(Attr<TValue, NullableReferenceHandleConverter<TValue, TConverter>> attribute, TValue value) where TValue : class where TConverter : IDynamoDbConverter<TValue>, IAddableConverter

Parameters

attribute Attr<TValue, NullableReferenceHandleConverter<TValue, TConverter>>

The attribute.

value TValue

The set.

Returns

UpdateStep

The command, which replaces this one.

Type Parameters

TValue

The type of the attribute.

TConverter

The converter, of a set: ADD takes nothing else, so an attribute of another type is a compile error.

Add<TValue, TConverter>(Attr<TValue, TConverter>, TValue)

Adds to a number, or adds elements to a set (ADD). An attribute that does not exist starts from zero or the empty set, and a negative number subtracts.

public UpdateStep Add<TValue, TConverter>(Attr<TValue, TConverter> attribute, TValue value) where TConverter : IDynamoDbConverter<TValue>, IAddableConverter

Parameters

attribute Attr<TValue, TConverter>

The attribute.

value TValue

The number or the set.

Returns

UpdateStep

The command, which replaces this one.

Type Parameters

TValue

The type of the attribute.

TConverter

The converter, of a number or a set: ADD takes nothing else, so an attribute of another type is a compile error.

Remarks

Taking stock. Add(Product.Attrs.Stock, -quantity) with If(Product.Attrs.Stock.Ge(quantity)) takes stock without going below zero.

A retry adds twice. A retry of the client after a lost response repeats the addition to a number, except in a transaction, whose attempts carry one ClientRequestToken, so DynamoDB applies it once. MaxAttempts(1) makes it at most once, not exact: a lost response then reports a failure after the addition was applied. Only a condition, such as a version, makes it exact.

Delete(string, AttributeValue)

Removes elements from a set (DELETE). A set that ends up empty disappears, as DynamoDB has no empty sets.

public UpdateStep Delete(string path, AttributeValue elements)

Parameters

path string

The name or document path.

elements AttributeValue

The elements, as a set.

Returns

UpdateStep

The command, which replaces this one.

Delete<TValue, TConverter>(Attr<TValue, TConverter>, TValue)

Removes elements from a set (DELETE). A set that ends up empty disappears, as DynamoDB has no empty sets.

public UpdateStep Delete<TValue, TConverter>(Attr<TValue, TConverter> attribute, TValue elements) where TConverter : IDynamoDbConverter<TValue>

Parameters

attribute Attr<TValue, TConverter>

The attribute.

elements TValue

The elements, as a set.

Returns

UpdateStep

The command, which replaces this one.

Type Parameters

TValue

The type of the attribute.

TConverter

The converter.

If(ExpressionHandler)

Adds a condition in the grammar of DynamoDB, for what the conditions of handles do not cover. An interpolated Attr stands for an attribute name and any other interpolated value for a value. If it does not hold, the whole transaction is cancelled, and a second condition means both must hold.

public UpdateStep If(ExpressionHandler condition)

Parameters

condition ExpressionHandler

The condition.

Returns

UpdateStep

The step, which replaces this one.

IfVersion(long)

Makes this update depend on the item having this version, and stores the next one. If it has another, the whole transaction is cancelled, and the marker of this action says that this was the reason.

public UpdateStep IfVersion(long version)

Parameters

version long

The version last read. A version of 0 stands for an item that does not exist, so it renders attribute_not_exists on the partition key. With Allow it stands for what reads as 0, an item without a version attribute or with 0 in it, or none.

Returns

UpdateStep

The step, which replaces this one.

Remarks

A key does not carry a version, so an update of an entity with a VersionAttribute needs this or IgnoreVersion(), and the next action throws InvalidOperationException without it. RetryOnConflictAsync<TResult>(Func<CancellationToken, ValueTask<TResult>>, CancellationToken) repeats a transaction together with the read of the version.

Exceptions

ArgumentOutOfRangeException

version is negative, or MaxValue, which has no next one.

InvalidOperationException

The table of this action has no VersionAttribute.

If<TCondition>(TCondition)

Adds a condition. If it does not hold, the whole transaction is cancelled, and a second condition means both must hold.

public UpdateStep If<TCondition>(TCondition condition) where TCondition : ICondition

Parameters

condition TCondition

The condition.

Returns

UpdateStep

The step, which replaces this one.

Type Parameters

TCondition

The type of the condition.

Exceptions

ArgumentNullException

condition is null.

IgnoreVersion()

Lets this update go out without the check of the version, and still stores the next version, so that a copy read before it fails its next checked write. See IgnoreVersion<T>(UpdateCommand<T>).

public UpdateStep IgnoreVersion()

Returns

UpdateStep

The step, which replaces this one.

Remarks

The version still advances. Every write of a versioned entity stores a new version, also one without the check: an update adds 1 to the stored version, SET #v = if_not_exists(#v, :zero) + :one, so an item without one, or a new item, gets version 1, and a put or a batch stores the version of its entity plus one, as a checked put does. A writer that holds a copy read before this write then fails with ConditionalCheckFailedException, or in a transaction with TransactionCanceledException, instead of overwriting it. What this write itself overwrites is not checked: it wins over whatever another writer stored since, so it suits a change that does not depend on what was read, such as an Add to a counter.

Setting the version yourself. An update that sets, adds to or removes the version attribute by its own action keeps that action, and the version is not advanced besides it. IfVersion(n) after this checks n and stores n + 1; before it, this throws.

Exceptions

InvalidOperationException

This update already has IfVersion, whose condition cannot be taken back.

MaxAttempts(int)

Sets the number of attempts of this call including the first, in place of MaxAttempts. A retry after a lost response repeats a write that may have been applied, so 1 makes an ADD count at most once, and a lost response then reports a failure after the write was applied.

public UpdateStep MaxAttempts(int attempts)

Parameters

attempts int

The number of attempts.

Returns

UpdateStep

The command, which replaces this one.

Exceptions

ArgumentOutOfRangeException

attempts is below 1.

Remove(string)

Removes an attribute (REMOVE), or an element of a list, which moves the elements after it. Removing what does not exist is no error.

public UpdateStep Remove(string path)

Parameters

path string

The name or document path.

Returns

UpdateStep

The command, which replaces this one.

Remove<TValue, TConverter>(Attr<TValue, TConverter>)

Removes an attribute (REMOVE), by its handle. Removing what does not exist is no error. A property that feeds a key of a sparse index takes the key attributes of that index with it, so that the item leaves the index; see Set<TValue, TConverter>(Attr<TValue, TConverter>, TValue?).

public UpdateStep Remove<TValue, TConverter>(Attr<TValue, TConverter> attribute) where TConverter : IDynamoDbConverter<TValue>

Parameters

attribute Attr<TValue, TConverter>

The attribute.

Returns

UpdateStep

The command, which replaces this one.

Type Parameters

TValue

The type of the attribute.

TConverter

The converter.

Set(ExpressionHandler)

Adds a SET action in the grammar of DynamoDB, for what the other forms do not cover, such as arithmetic and list_append: .Set($"{Attr("total")} = {Attr("total")} + {5}"). An interpolated Attr stands for an attribute name and any other interpolated value for a value.

public UpdateStep Set(ExpressionHandler action)

Parameters

action ExpressionHandler

The action.

Returns

UpdateStep

The step, which replaces this one.

Set(string, AttributeValue)

Sets an attribute, creating it if it does not exist (SET).

public UpdateStep Set(string path, AttributeValue value)

Parameters

path string

The name or document path. The parent of a nested path must exist.

value AttributeValue

The value.

Returns

UpdateStep

The command, which replaces this one.

SetIfNotExists(string, AttributeValue)

Sets an attribute unless it exists (SET a = if_not_exists(a, value)).

public UpdateStep SetIfNotExists(string path, AttributeValue value)

Parameters

path string

The name or document path.

value AttributeValue

The value.

Returns

UpdateStep

The command, which replaces this one.

SetIfNotExists<TNumber>(string, TNumber)

Sets a number attribute unless it exists (SET a = if_not_exists(a, value)).

public UpdateStep SetIfNotExists<TNumber>(string path, TNumber value) where TNumber : INumberBase<TNumber>

Parameters

path string

The name or document path.

value TNumber

The number.

Returns

UpdateStep

The step, which replaces this one.

Type Parameters

TNumber

The type of the number.

SetIfNotExists<TValue, TConverter>(Attr<TValue, TConverter>, TValue)

Sets an attribute unless it exists (SET a = if_not_exists(a, value)).

public UpdateStep SetIfNotExists<TValue, TConverter>(Attr<TValue, TConverter> attribute, TValue value) where TConverter : IDynamoDbConverter<TValue>

Parameters

attribute Attr<TValue, TConverter>

The attribute.

value TValue

The value.

Returns

UpdateStep

The command, which replaces this one.

Type Parameters

TValue

The type of the attribute.

TConverter

The converter.

Exceptions

ArgumentNullException

value is null.

ArgumentException

value is empty, on a property with OmitEmptyAttribute, which counts that as null, or anything else that IsOmitted(T) of the converter counts as null.

SetIfNotNull<TValue, TConverter>(Attr<TValue, TConverter>, TValue?)

Sets an attribute of a value type if the nullable value has a value, and adds nothing if it has none. With a value it costs what Set<TValue, TConverter>(Attr<TValue, TConverter>, TValue?) costs. See SetIfNotNull<TValue, TConverter>(Attr<TValue, TConverter>, TValue?).

public UpdateStep SetIfNotNull<TValue, TConverter>(Attr<TValue, TConverter> attribute, TValue? value) where TValue : struct where TConverter : IDynamoDbConverter<TValue>

Parameters

attribute Attr<TValue, TConverter>

The attribute.

value TValue?

The value, or null to leave the attribute alone.

Returns

UpdateStep

The command, which replaces this one.

Type Parameters

TValue

The type of the attribute.

TConverter

The converter.

SetIfNotNull<TValue, TConverter>(Attr<TValue, TConverter>, TValue?)

Sets an attribute if there is a value, and leaves it as it is if the value is null, which is what an update of optional fields wants: .SetIfNotNull(Customer.Attrs.Email, request.Email).

public UpdateStep SetIfNotNull<TValue, TConverter>(Attr<TValue, TConverter> attribute, TValue? value) where TConverter : IDynamoDbConverter<TValue>

Parameters

attribute Attr<TValue, TConverter>

The attribute.

value TValue

The value, or null to leave the attribute alone.

Returns

UpdateStep

The command, which replaces this one.

Type Parameters

TValue

The type of the attribute.

TConverter

The converter.

Remarks

With a value it is Set<TValue, TConverter>(Attr<TValue, TConverter>, TValue?), with all it says about keys. With null the attribute stays as it is, where Set would remove it, and a property that feeds a key counts as untouched. On a property with OmitEmptyAttribute an empty string or collection is no value either. An update that ends up with no action is still an UpdateItem: it checks its conditions, creates the item if none has the key, and writes what the entity owes it, such as its discriminator.

Set<TNumber>(string, TNumber)

Sets a number attribute, creating it if it does not exist (SET).

public UpdateStep Set<TNumber>(string path, TNumber value) where TNumber : INumberBase<TNumber>

Parameters

path string

The name or document path. The parent of a nested path must exist.

value TNumber

The number.

Returns

UpdateStep

The step, which replaces this one.

Type Parameters

TNumber

The type of the number.

Set<TValue, TConverter>(Attr<TValue, TConverter>, TValue?)

Sets an attribute of a value type from a nullable value, which is what a nullable property holds, or removes it when there is no value: a Nullable<T> with a value is Set<TValue, TConverter>(Attr<TValue, TConverter>, TValue?) at the same cost, and without one it is Remove<TValue, TConverter>(Attr<TValue, TConverter>). The rules of a property that feeds a key are the ones of those two.

public UpdateStep Set<TValue, TConverter>(Attr<TValue, TConverter> attribute, TValue? value) where TValue : struct where TConverter : IDynamoDbConverter<TValue>

Parameters

attribute Attr<TValue, TConverter>

The attribute.

value TValue?

The value, or null to remove the attribute.

Returns

UpdateStep

The command, which replaces this one.

Type Parameters

TValue

The type of the attribute.

TConverter

The converter.

Set<TValue, TConverter>(Attr<TValue, TConverter>, TValue?)

Sets an attribute, creating it if it does not exist (SET), and keeps every key made from it consistent, or throws when the command ends. A null value is a Remove<TValue, TConverter>(Attr<TValue, TConverter>), for every attribute, because a generated entity writes no attribute for a null property either. On a property with OmitEmptyAttribute an empty string or collection is one too.

public UpdateStep Set<TValue, TConverter>(Attr<TValue, TConverter> attribute, TValue? value) where TConverter : IDynamoDbConverter<TValue>

Parameters

attribute Attr<TValue, TConverter>

The attribute.

value TValue

The value, or null to remove the attribute.

Returns

UpdateStep

The command, which replaces this one.

Type Parameters

TValue

The type of the attribute.

TConverter

The converter.

Remarks

Key templates. The handle of a property that feeds a key template keeps that key consistent, which a raw path does not. When the command ends, all inputs of the template must be known: then the derived attribute is written in the same SET, and otherwise sending throws InvalidOperationException naming the template and the Set calls to add, because the index would go stale. An update expression can copy an attribute and cannot format one, so an input of a key of several values or with literals that does not change is set as well, to the value the item holds. An input of a key of the table is known from the key the update was given, and it cannot be set, because DynamoDB cannot update a key, so an index key that repeats it needs nothing more: that is the place for an input that never changes. A key given as strings is parsed for that, so a value that its text does not hold, such as a timestamp a key cuts off at the day, comes from a generated key or not at all: then use a Put of the changed entity, or a raw path. A write by handle to a property that a computed input is derived from, see ComputedFromAttribute, also to a path inside it, throws in the same way, because no update can run a getter, and so does a write by handle to such a computed input itself.

Sparse indexes. An index takes an item only with all its keys, so setting one key of a sparse index needs the other one in the same update, or sending throws InvalidOperationException naming it: an update does not read the item, so it cannot tell whether the item holds the other key, and an item without it would stay out of the index without an error. A key of literals, of any index, and a key made only of inputs of the table key are no such keys: they are written in the same SET, and removed with the other key. A key that is the stored text of an attribute, one bare placeholder such as {Owner} over a string, also with :raw, a Guid, a DateOnly, a timestamp in ticks or an enum by name, each with its built-in converter, is copied in the same SET, gsi1pk = Owner, so the update needs no value for it. DynamoDB evaluates the copy on the item: an item without the attribute, also one that the update would create, fails the whole update with ValidationException, "The provided expression refers to an attribute that does not exist in the item", and is left as it was.

Add and SetIfNotExists. By the handle of such a property they throw too: the value they leave is not known here, so the key cannot follow. In a transaction the check runs when the action ends, at the next verb.

StoreKeyInputs()

Stores the inputs of the key of the table as attributes of the item, as a Put does, for an update that may create the item: without it, an item an update created holds the key alone. See StoreKeyInputs<T>(UpdateCommand<T>).

public UpdateStep StoreKeyInputs()

Returns

UpdateStep

The step, which replaces this one.

Remarks

What is written. SET #userId = if_not_exists(#userId, :v) per input, after the actions of the update and the keys of its indexes and before the discriminator. An item that exists keeps what it has, so this goes with IfExists(), IfNotExists() and a version alike. The value goes through the converter of the property and is the value, not the text of the key, and an action of the update on the attribute by a path given as a string takes precedence.

Why. A read of the entity restores the inputs from the key, but Select of such an input and a filter on it find nothing in an item that holds the key alone. A plain key and a key made of one property over its own attribute are their attribute, and a KeyOnlyAttribute has none, so an entity with nothing else changes nothing here.

A key given as strings. A template that cuts a value off, such as a timestamp in {At:yyyy-MM-dd}, gives it back only from a key the generator built, so a key given as strings throws for it when the update ends.

In a transaction such a throw comes from the next action, where this action settles.

Exceptions

InvalidOperationException

The table of this action has no entity.

ToRequestJson()

Renders the body this transaction would send, as DynamoDB JSON, without sending it. It ends the command, and is meant for tests and debugging. The text contains the items and a generated token that nothing ever sends.

public string ToRequestJson()

Returns

string

The request body.

Exceptions

InvalidOperationException

The command was already sent, extended or rendered, or it has no action, which DynamoDB would reject.

Operators

implicit operator TransactWriteCommand(UpdateStep)

Hands the transaction on as a TransactWriteCommand, which is what a variable holds across a loop: tx = tx.Update(table, key).Add(attribute, 1);. This uses the step up like any call on it, so the command is the one handle left, and a clause of the action can no longer follow. What the action still owes, such as a version, is checked by the next verb.

public static implicit operator TransactWriteCommand(UpdateStep step)

Parameters

step UpdateStep

The step, which this replaces.

Returns

TransactWriteCommand

Exceptions

InvalidOperationException

The step was already sent, extended or rendered.