Back to Redis

Conditional execution

content/develop/clients/dotnet/condexec.md

latest7.3 KB
Original Source

Most Redis client libraries use transactions with the [WATCH]({{< relref "/commands/watch" >}}) command as the main way to prevent two clients writing to the same key at once (see [Transactions]({{< relref "develop/using-commands/transactions" >}}) for more information). Unfortunately, this approach is difficult to use explicitly in NRedisStack. Its [multiplexing]({{< relref "/develop/clients/pools-and-muxing" >}}) system is highly efficient and convenient but can also cause bad interactions when different connections use watched transactions at the same time.

Instead, NRedisStack relies more heavily on conditional execution. This comes in two basic forms, When conditions and transaction conditions, both of which are explained in the sections below.

When conditions

Several commands have variants that only execute if the key they change already exists (or alternatively, if it doesn't already exist). For example, the [SET]({{< relref "/commands/set" >}}) command has the variants [SETEX]({{< relref "/commands/setex" >}}) (set when the key exists), and [SETNX]({{< relref "/commands/setnx" >}}) (set when the key doesn't exist).

Instead of providing the different variants of these commands, NRedisStack lets you add a When condition to the basic command to access its variants. The following example demonstrates this for the [HashSet()]({{< relref "/commands/hset" >}}) command.

<!-- < clients-example pipe_trans_tutorial when_condition "C#" >}} < /clients-example >}} -->
csharp
bool resp7 = db.HashSet("Details", "SerialNumber", "12345");
Console.WriteLine(resp7); // >>> true

db.HashSet("Details", "SerialNumber", "12345A", When.NotExists);
string resp8 = db.HashGet("Details", "SerialNumber");
Console.WriteLine(resp8); // >>> 12345

db.HashSet("Details", "SerialNumber", "12345A");
string resp9 = db.HashGet("Details", "SerialNumber");
Console.WriteLine(resp9); // >>> 12345A

The available conditions are When.Exists, When.NotExists, and the default When.Always.

Transaction conditions

NRedisStack also supports a more extensive set of conditions that you can add to transactions. They are implemented internally using [WATCH]({{< relref "/commands/watch" >}}) commands in a way that is guaranteed to be safe, without interactions between different clients. Although conditions don't provide exactly the same behavior as explicit WATCH commands, they are convenient to use and execute efficiently.

The example below shows how to use the AddCondition() method on a transaction to let it run only if a specified hash key does not already exist. See [Pipelines and transactions]({{< relref "/develop/clients/dotnet/transpipe" >}}) for more information about transactions.

<!--< clients-example pipe_trans_tutorial trans_watch "C#" >}} < /clients-example >}} -->
csharp
var watchedTrans = new Transaction(db);

watchedTrans.AddCondition(Condition.KeyNotExists("customer:39182"));

watchedTrans.Db.HashSetAsync(
    "customer:39182",
    new HashEntry[]{
        new HashEntry("name", "David"),
        new HashEntry("age", "27")
    }
);

bool succeeded = watchedTrans.Execute();
Console.WriteLine(succeeded); // >>> true

The table below describes the full set of conditions you can add to a transaction. Note that you can add more than one condition to the same transaction if necessary.

ConditionDescription
HashEqualEnforces that the given hash-field must have the specified value.
HashExistsEnforces that the given hash-field must exist.
HashNotEqualEnforces that the given hash-field must not have the specified value.
HashNotExistsEnforces that the given hash-field must not exist.
KeyExistsEnforces that the given key must exist.
KeyNotExistsEnforces that the given key must not exist.
ListIndexEqualEnforces that the given list index must have the specified value.
ListIndexExistsEnforces that the given list index must exist.
ListIndexNotEqualEnforces that the given list index must not have the specified value.
ListIndexNotExistsEnforces that the given list index must not exist.
StringEqualEnforces that the given key must have the specified value.
StringNotEqualEnforces that the given key must not have the specified value.
HashLengthEqualEnforces that the given hash length is a certain value.
HashLengthLessThanEnforces that the given hash length is less than a certain value.
HashLengthGreaterThanEnforces that the given hash length is greater than a certain value.
StringLengthEqualEnforces that the given string length is a certain value.
StringLengthLessThanEnforces that the given string length is less than a certain value.
StringLengthGreaterThanEnforces that the given string length is greater than a certain value.
ListLengthEqualEnforces that the given list length is a certain value.
ListLengthLessThanEnforces that the given list length is less than a certain value.
ListLengthGreaterThanEnforces that the given list length is greater than a certain value.
SetLengthEqualEnforces that the given set cardinality is a certain value.
SetLengthLessThanEnforces that the given set cardinality is less than a certain value.
SetLengthGreaterThanEnforces that the given set cardinality is greater than a certain value.
SetContainsEnforces that the given set contains a certain member.
SetNotContainsEnforces that the given set does not contain a certain member.
SortedSetLengthEqualEnforces that the given sorted set cardinality is a certain value.
SortedSetLengthEqualEnforces that the given sorted set contains a certain number of members with scores in the given range.
SortedSetLengthLessThanEnforces that the given sorted set cardinality is less than a certain value.
SortedSetLengthLessThanEnforces that the given sorted set contains less than a certain number of members with scores in the given range.
SortedSetLengthGreaterThanEnforces that the given sorted set cardinality is greater than a certain value.
SortedSetLengthGreaterThanEnforces that the given sorted set contains more than a certain number of members with scores in the given range.
SortedSetContainsEnforces that the given sorted set contains a certain member.
SortedSetNotContainsEnforces that the given sorted set does not contain a certain member.
SortedSetEqualEnforces that the given sorted set member must have the specified score.
SortedSetNotEqualEnforces that the given sorted set member must not have the specified score.
SortedSetScoreExistsEnforces that the given sorted set must have the given score.
SortedSetScoreNotExistsEnforces that the given sorted set must not have the given score.
SortedSetScoreExistsEnforces that the given sorted set must have the specified count of the given score.
SortedSetScoreNotExistsEnforces that the given sorted set must not have the specified count of the given score.
StreamLengthEqualEnforces that the given stream length is a certain value.
StreamLengthLessThanEnforces that the given stream length is less than a certain value.
StreamLengthGreaterThanEnforces that the given stream length is greater than a certain value.