Table of Contents

Struct MixedQueryCommand<TMixed>

Namespace
DynaSharp
Assembly
DynaSharp.dll

A Query that reads several entity types of one partition, the adjacency list of a single table: shop.Query(pk).Of<Customer, Order>(). It has the clauses of QueryCommand<T> and every way to send it but CountAsync, because a count has nothing to dispatch.

public readonly ref struct MixedQueryCommand<TMixed> : IFilterable<MixedQueryCommand<TMixed>>, IRetryable<MixedQueryCommand<TMixed>> where TMixed : IMixed<TMixed>

Type Parameters

TMixed

The item of the read, Mixed<T1, T2> or one of its siblings of 3 and 4 types, which name the entity types.

Implements
Inherited Members

Remarks

The filter gains #_type IN (:a, :b), in the request for everyone to see, so items of other types never reach the client. Filters run after the read: ScannedCount exceeds Count by the items of other types, and capacity is charged for them all. A table or index keyed by the discriminator is the exception, because DynamoDB refuses a filter on a key of what a query reads: the request has none, the key condition has to keep other types out, and an item of another type throws DynamoDbMappingException.

An item finds its type through its discriminator, wherever that stands among its attributes, and is read by the mapping of that type with no Item in between. An item that a type cannot read throws DynamoDbMappingException. A projection gains the discriminator and the keys of the types.

Methods

Consistent()

Asks for a strongly consistent read, which sees every write that succeeded before it and costs twice the capacity. A read is eventually consistent otherwise.

public MixedQueryCommand<TMixed> Consistent()

Returns

MixedQueryCommand<TMixed>

The command, which replaces this one.

Remarks

A global secondary index is always eventually consistent, so this throws on one that is known to be global, which is an index opened through its entity or one with another partition key than the table, and DynamoDB answers with a ValidationException for any other.

Exceptions

InvalidOperationException

The index is known to be global.

Descending()

Reads the sort key downwards, so that the newest of a time-ordered partition come first (ScanIndexForward: false). It costs the same.

public MixedQueryCommand<TMixed> Descending()

Returns

MixedQueryCommand<TMixed>

The command, which replaces this one.

Filter(ExpressionHandler)

Adds a filter in the grammar of DynamoDB, for what the conditions of handles do not cover: .Filter($"size({Attr("tags")}) < {10}"). DynamoDB applies it after reading, so capacity is charged for every item read, not for those returned.

public MixedQueryCommand<TMixed> Filter(ExpressionHandler condition)

Parameters

condition ExpressionHandler

The condition.

Returns

MixedQueryCommand<TMixed>

The command, which replaces this one.

Remarks

An interpolated Attr stands for an attribute name and any other interpolated value for a value. A page can come back empty. A filter cannot name a key of the table or index that is read; that is what the key condition is for. A second filter means both must hold.

Filter<TCondition>(TCondition)

Adds a filter. DynamoDB applies it after reading, so it shortens the result, not the read: capacity is charged for every item scanned, and a page can come back empty. A second filter means both must hold.

public MixedQueryCommand<TMixed> Filter<TCondition>(TCondition condition) where TCondition : ICondition

Parameters

condition TCondition

The condition.

Returns

MixedQueryCommand<TMixed>

The command, which replaces this one.

Type Parameters

TCondition

The type of the condition.

ItemsAsync(CancellationToken)

Reads all items of all pages as they come, following pages that a filter left empty. Nothing is sent until the enumeration starts, and only what the enumeration reaches is read, so breaking out early saves the remaining pages. Capacity is charged for the items scanned, which with a filter can be far more than those returned; it is not reported here, only on the spans and the metric, see PagesAsync(CancellationToken).

public IAsyncEnumerable<TMixed> ItemsAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

Cancels the read, as does WithCancellation on the result. It is looked at per page.

Returns

IAsyncEnumerable<TMixed>

The items, which can be enumerated once; a second enumeration throws InvalidOperationException, so build the command again to read again.

Exceptions

InvalidOperationException

The command was already sent, extended or rendered.

Limit(int)

Limits the items DynamoDB reads per page, before the filter. It does not limit the result: ItemsAsync(CancellationToken) reads on until the end, in pages of this size, and with a filter a page holds fewer items than this. A cap on items is .ItemsAsync(ct).Take(n), which reads until it has them, across empty filtered pages, and stops. To read one page, use PageAsync(ContinuationToken, CancellationToken).

public MixedQueryCommand<TMixed> Limit(int items)

Parameters

items int

The most items per page.

Returns

MixedQueryCommand<TMixed>

The command, which replaces this one.

Remarks

Other entities in the partition. A read of an entity with a discriminator filters on it (#_type = :t), so that a table shared by several types gives back its own items, and that filter is in the request for everyone to see. DynamoDB applies it after reading, so the items of other entities under the same partition key are still read: they count against Limit(int) and the capacity, and are in ScannedCount but not in Count or Items. orders.Query(Order.Keys.Pk.Of("dana")).Limit(10) gives 9 orders in its first page when the profile of the customer shares the partition. A condition on the sort key that only this entity matches, orders.Query(Order.Keys.Pk.Of("dana"), Order.Keys.Sk.BeginsWith()), reads its items alone. To read several types at once, read the table as Item.

Exceptions

ArgumentOutOfRangeException

items is below 1.

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 MixedQueryCommand<TMixed> MaxAttempts(int attempts)

Parameters

attempts int

The number of attempts.

Returns

MixedQueryCommand<TMixed>

The command, which replaces this one.

Exceptions

ArgumentOutOfRangeException

attempts is below 1.

OnMappingFailure(Action<DynamoDbMappingException>)

Skips an item that none of the types can read, or that its type cannot read, and hands its DynamoDbMappingException to onFailure, where the read would otherwise end with it. See OnMappingFailure(Action<DynamoDbMappingException>).

public MixedQueryCommand<TMixed> OnMappingFailure(Action<DynamoDbMappingException> onFailure)

Parameters

onFailure Action<DynamoDbMappingException>

What to do with the failure of a skipped item.

Returns

MixedQueryCommand<TMixed>

The command, which replaces this one.

Exceptions

ArgumentNullException

onFailure is null.

PageAsync(ContinuationToken, CancellationToken)

Reads one page, for paging that a client drives across requests: build the same query each time and pass the position of the page before. The page can be empty and still have a next one, so a client that wants items keeps going while HasMore holds.

public ValueTask<Page<TMixed>> PageAsync(ContinuationToken after = default, CancellationToken cancellationToken = default)

Parameters

after ContinuationToken

The position to continue from, or default for the first page. It must come from the same query. A ContinuationToken? passes as after ?? default.

cancellationToken CancellationToken

Cancels the call.

Returns

ValueTask<Page<TMixed>>

The page. Await it once.

Remarks

Other entities in the partition. A read of an entity with a discriminator filters on it (#_type = :t), so that a table shared by several types gives back its own items, and that filter is in the request for everyone to see. DynamoDB applies it after reading, so the items of other entities under the same partition key are still read: they count against Limit(int) and the capacity, and are in ScannedCount but not in Count or Items. orders.Query(Order.Keys.Pk.Of("dana")).Limit(10) gives 9 orders in its first page when the profile of the customer shares the partition. A condition on the sort key that only this entity matches, orders.Query(Order.Keys.Pk.Of("dana"), Order.Keys.Sk.BeginsWith()), reads its items alone. To read several types at once, read the table as Item.

Exceptions

InvalidOperationException

The command was already sent, extended or rendered.

ObjectDisposedException

The client is disposed.

FormatException

after does not fit what TokenSigner says: a client that signs gets a plain token that came as text, or one whose signature does not hold for this read; a client that does not sign gets a signed one. The message quotes nothing of the token, and no request goes out.

ValidationException

DynamoDB rejects the request, for example a position of another query; the exception shows the expressions.

ResourceNotFoundException

The table does not exist.

DynamoDbMappingException

An item cannot be read as T.

DynamoDbException

DynamoDB returns any other error; a throttling or server error only after the last attempt.

PageAsync(CancellationToken)

Reads the first page, as PageAsync(ContinuationToken, CancellationToken) does at the default position, for a caller that has a token and no position yet.

public ValueTask<Page<TMixed>> PageAsync(CancellationToken cancellationToken)

Parameters

cancellationToken CancellationToken

Cancels the call. It has no default, because PageAsync() belongs to the overload with the position.

Returns

ValueTask<Page<TMixed>>

The page. Await it once.

Exceptions

InvalidOperationException

The command was already sent, extended or rendered.

ObjectDisposedException

The client is disposed.

ValidationException

DynamoDB rejects the request; the exception shows the expressions.

ResourceNotFoundException

The table does not exist.

DynamoDbMappingException

An item cannot be read as T.

DynamoDbException

DynamoDB returns any other error; a throttling or server error only after the last attempt.

PagesAsync(CancellationToken)

Reads all pages as they come, for code that wants ConsumedCapacity or works page by page. It gives every response, also one that a filter left empty. Otherwise as ItemsAsync(CancellationToken).

public IAsyncEnumerable<Page<TMixed>> PagesAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

Cancels the read, as does WithCancellation on the result.

Returns

IAsyncEnumerable<Page<TMixed>>

The pages, which can be enumerated once.

Exceptions

InvalidOperationException

The command was already sent, extended or rendered.

Project(params ReadOnlySpan<Attr>)

Reads only some attributes, given as handles: Project(Order.Attrs.Status, Order.Attrs.Total). See Project(params ReadOnlySpan<string>).

public MixedQueryCommand<TMixed> Project(params ReadOnlySpan<Attr> attributes)

Parameters

attributes ReadOnlySpan<Attr>

The attributes. A second call adds to the first.

Returns

MixedQueryCommand<TMixed>

The command, which replaces this one.

Exceptions

ArgumentException

A path is not valid.

Project(params ReadOnlySpan<string>)

Reads only some attributes. It saves bandwidth, not capacity: DynamoDB charges for whole items. A read of an entity needs its discriminator and its keys, so they join the projection on their own, and it needs whatever else the entity requires, so a projection is mostly for Item. A global secondary index gives only what it projects.

public MixedQueryCommand<TMixed> Project(params ReadOnlySpan<string> paths)

Parameters

paths ReadOnlySpan<string>

The names or document paths. Reserved words need no care, and a second call adds to the first.

Returns

MixedQueryCommand<TMixed>

The command, which replaces this one.

Exceptions

ArgumentException

A path is not valid.

ReturnCapacity(ReturnConsumedCapacity)

Asks for the consumed capacity of each page, which goes to ConsumedCapacity, the span of the page and the capacity metric. ItemsAsync(CancellationToken) has no result to put it on, so there it reaches telemetry only.

public MixedQueryCommand<TMixed> ReturnCapacity(ReturnConsumedCapacity detail = ReturnConsumedCapacity.Total)

Parameters

detail ReturnConsumedCapacity

How much detail to return.

Returns

MixedQueryCommand<TMixed>

The command, which replaces this one.

ToRequestJson()

Renders the body of the first page, as DynamoDB JSON, without sending it. It ends the command, and is meant for tests and debugging. The text contains the key and the values.

public string ToRequestJson()

Returns

string

The request body.

Exceptions

InvalidOperationException

The command was already sent, extended or rendered.