|
| 1 | +--- |
| 2 | +categories: |
| 3 | +- docs |
| 4 | +- develop |
| 5 | +- stack |
| 6 | +- oss |
| 7 | +- rs |
| 8 | +- rc |
| 9 | +- oss |
| 10 | +- kubernetes |
| 11 | +- clients |
| 12 | +description: Understand how `NRedisStack` uses conditional execution |
| 13 | +linkTitle: Conditional execution |
| 14 | +title: Conditional execution |
| 15 | +weight: 6 |
| 16 | +--- |
| 17 | + |
| 18 | +Most Redis client libraries use transactions with the |
| 19 | +[`WATCH`]({{< relref "/commands/watch" >}}) command as the main way to prevent |
| 20 | +two clients writing to the same key at once (see [Transactions]({{< relref "/develop/interact/transactions" >}}) for more information). Unfortunately, this approach is |
| 21 | +difficult to use explicitly in `NRedisStack`. Its |
| 22 | +[multiplexing]({{< relref "/develop/clients/pools-and-muxing" >}}) system |
| 23 | +is highly efficient and convenient but can also cause bad interactions |
| 24 | +when different connections use watched transactions at the same time. |
| 25 | + |
| 26 | +Instead, `NRedisStack` relies more heavily on conditional execution. This comes |
| 27 | +in two basic forms, `When` conditions and transaction conditions, both of which |
| 28 | +are explained in the sections below. |
| 29 | + |
| 30 | +## `When` conditions |
| 31 | + |
| 32 | +Several commands have variants that only execute if the key they change |
| 33 | +already exists (or alternatively, if it doesn't already exist). For |
| 34 | +example, the [`SET`]({{< relref "/commands/set" >}}) command has the |
| 35 | +variants [`SETEX`]({{< relref "/commands/setex" >}}) (set when the key exists), |
| 36 | +and [`SETNX`]({{< relref "/commands/setnx" >}}) (set when the key doesn't exist). |
| 37 | + |
| 38 | +Instead of providing the different variants of these commands, `NRedisStack` |
| 39 | +lets you add a `When` condition to the basic command to access its variants. |
| 40 | +The following example demonstrates this for the |
| 41 | +[`HashSet()`]({{< relref "/commands/hset" >}}) command. |
| 42 | + |
| 43 | +<!-- < clients-example pipe_trans_tutorial when_condition "C#" >}} |
| 44 | +< /clients-example >}} --> |
| 45 | + |
| 46 | +```csharp |
| 47 | +bool resp7 = db.HashSet("Details", "SerialNumber", "12345"); |
| 48 | +Console.WriteLine(resp7); // >>> true |
| 49 | +
|
| 50 | +db.HashSet("Details", "SerialNumber", "12345A", When.NotExists); |
| 51 | +string resp8 = db.HashGet("Details", "SerialNumber"); |
| 52 | +Console.WriteLine(resp8); // >>> 12345 |
| 53 | +
|
| 54 | +db.HashSet("Details", "SerialNumber", "12345A"); |
| 55 | +string resp9 = db.HashGet("Details", "SerialNumber"); |
| 56 | +Console.WriteLine(resp9); // >>> 12345A |
| 57 | +``` |
| 58 | + |
| 59 | +The available conditions are `When.Exists`, `When.NotExists`, and the default |
| 60 | +`When.Always`. |
| 61 | + |
| 62 | +## Transaction conditions |
| 63 | + |
| 64 | +`NRedisStack` also supports a more extensive set of conditions that you |
| 65 | +can add to transactions. They are implemented internally using |
| 66 | +[`WATCH`]({{< relref "/commands/watch" >}}) commands in a way that is |
| 67 | +guaranteed to be safe, without interactions between different clients. |
| 68 | +Although conditions don't provide exactly the same behavior as |
| 69 | +explicit `WATCH` commands, they are convenient to use and execute |
| 70 | +efficiently. |
| 71 | + |
| 72 | +The example below shows how to use the `AddCondition()` method on |
| 73 | +a transaction to let it run only if a specified hash key does not |
| 74 | +already exist. See |
| 75 | +[Pipelines and transactions]({{< relref "/develop/clients/dotnet/transpipe" >}}) |
| 76 | +for more information about transactions. |
| 77 | + |
| 78 | +<!--< clients-example pipe_trans_tutorial trans_watch "C#" >}} |
| 79 | +< /clients-example >}} --> |
| 80 | + |
| 81 | +```csharp |
| 82 | +var watchedTrans = new Transaction(db); |
| 83 | + |
| 84 | +watchedTrans.AddCondition(Condition.KeyNotExists("customer:39182")); |
| 85 | + |
| 86 | +watchedTrans.Db.HashSetAsync( |
| 87 | + "customer:39182", |
| 88 | + new HashEntry[]{ |
| 89 | + new HashEntry("name", "David"), |
| 90 | + new HashEntry("age", "27") |
| 91 | + } |
| 92 | +); |
| 93 | + |
| 94 | +bool succeeded = watchedTrans.Execute(); |
| 95 | +Console.WriteLine(succeeded); // >>> true |
| 96 | +``` |
| 97 | + |
| 98 | +The table below describes the full set of conditions you can add to |
| 99 | +a transaction. Note that you can add more than one condition to the |
| 100 | +same transaction if necessary. |
| 101 | + |
| 102 | +| Condition | Description | |
| 103 | +| :-- | :-- | |
| 104 | +| `HashEqual` | Enforces that the given hash-field must have the specified value. | |
| 105 | +| `HashExists` | Enforces that the given hash-field must exist. | |
| 106 | +| `HashNotEqual` | Enforces that the given hash-field must not have the specified value. | |
| 107 | +| `HashNotExists` | Enforces that the given hash-field must not exist. | |
| 108 | +| `KeyExists` | Enforces that the given key must exist. | |
| 109 | +| `KeyNotExists` | Enforces that the given key must not exist. | |
| 110 | +| `ListIndexEqual` | Enforces that the given list index must have the specified value. | |
| 111 | +| `ListIndexExists` | Enforces that the given list index must exist. | |
| 112 | +| `ListIndexNotEqual` | Enforces that the given list index must not have the specified value. | |
| 113 | +| `ListIndexNotExists` | Enforces that the given list index must not exist. | |
| 114 | +| `StringEqual` | Enforces that the given key must have the specified value. | |
| 115 | +| `StringNotEqual` | Enforces that the given key must not have the specified value. | |
| 116 | +| `HashLengthEqual` | Enforces that the given hash length is a certain value. | |
| 117 | +| `HashLengthLessThan` | Enforces that the given hash length is less than a certain value. | |
| 118 | +| `HashLengthGreaterThan` | Enforces that the given hash length is greater than a certain value. | |
| 119 | +| `StringLengthEqual` | Enforces that the given string length is a certain value. | |
| 120 | +| `StringLengthLessThan` | Enforces that the given string length is less than a certain value. | |
| 121 | +| `StringLengthGreaterThan` | Enforces that the given string length is greater than a certain value. | |
| 122 | +| `ListLengthEqual` | Enforces that the given list length is a certain value. | |
| 123 | +| `ListLengthLessThan` | Enforces that the given list length is less than a certain value. | |
| 124 | +| `ListLengthGreaterThan` | Enforces that the given list length is greater than a certain value. | |
| 125 | +| `SetLengthEqual` | Enforces that the given set cardinality is a certain value. | |
| 126 | +| `SetLengthLessThan` | Enforces that the given set cardinality is less than a certain value. | |
| 127 | +| `SetLengthGreaterThan` | Enforces that the given set cardinality is greater than a certain value. | |
| 128 | +| `SetContains` | Enforces that the given set contains a certain member. | |
| 129 | +| `SetNotContains` | Enforces that the given set does not contain a certain member. | |
| 130 | +| `SortedSetLengthEqual` | Enforces that the given sorted set cardinality is a certain value. | |
| 131 | +| `SortedSetLengthEqual` | Enforces that the given sorted set contains a certain number of members with scores in the given range. | |
| 132 | +| `SortedSetLengthLessThan` | Enforces that the given sorted set cardinality is less than a certain value. | |
| 133 | +| `SortedSetLengthLessThan` | Enforces that the given sorted set contains less than a certain number of members with scores in the given range. | |
| 134 | +| `SortedSetLengthGreaterThan` | Enforces that the given sorted set cardinality is greater than a certain value. | |
| 135 | +| `SortedSetLengthGreaterThan` | Enforces that the given sorted set contains more than a certain number of members with scores in the given range. | |
| 136 | +| `SortedSetContains` | Enforces that the given sorted set contains a certain member. | |
| 137 | +| `SortedSetNotContains` | Enforces that the given sorted set does not contain a certain member. | |
| 138 | +| `SortedSetEqual` | Enforces that the given sorted set member must have the specified score. | |
| 139 | +| `SortedSetNotEqual` | Enforces that the given sorted set member must not have the specified score. | |
| 140 | +| `SortedSetScoreExists` | Enforces that the given sorted set must have the given score. | |
| 141 | +| `SortedSetScoreNotExists` | Enforces that the given sorted set must not have the given score. | |
| 142 | +| `SortedSetScoreExists` | Enforces that the given sorted set must have the specified count of the given score. | |
| 143 | +| `SortedSetScoreNotExists` | Enforces that the given sorted set must not have the specified count of the given score. | |
| 144 | +| `StreamLengthEqual` | Enforces that the given stream length is a certain value. | |
| 145 | +| `StreamLengthLessThan` | Enforces that the given stream length is less than a certain value. | |
| 146 | +| `StreamLengthGreaterThan` | Enforces that the given stream length is greater than a certain value. | |
0 commit comments