Marc的答案很有用,但在我的情況下,它導致了大量的代碼膨脹(並且很容易忘記這樣做),所以我想出了一種抽象來實現這種模式。
這裏是你如何使用它:
await db.TransactAsync(commands => commands
.Enqueue(tran => tran.SomeCommandAsync(...))
.Enqueue(tran => tran.SomeCommandAsync(...))
.Enqueue(tran => tran.SomeCommandAsync(...)));
這裏的實現:
public static class RedisExtensions
{
public static async Task TransactAsync(this IDatabase db, Action<RedisCommandQueue> addCommands)
{
var tran = db.CreateTransaction();
var q = new RedisCommandQueue(tran);
addCommands(q);
if (await tran.ExecuteAsync())
await q.CompleteAsync();
}
}
public class RedisCommandQueue
{
private readonly ITransaction _tran;
private readonly IList<Task> _tasks = new List<Task>();
public RedisCommandQueue Enqueue(Func<ITransaction, Task> cmd)
{
_tasks.Add(cmd(_tran));
return this;
}
internal RedisCommandQueue(ITransaction tran) => _tran = tran;
internal Task CompleteAsync() => Task.WhenAll(_tasks);
}
警告:這並沒有提供一種簡單的方式來獲得在任何的結果命令。在我的情況下(和OP的)沒關係 - 我總是使用事務進行一系列寫操作。我發現這確實有助於削減我的代碼,並且只在Enqueue
(它要求您返回任務)內暴露tran
,我不太可能「忘記」我當時不應該使用這些命令我打電話給他們。
我的意思是暫時還沒有提供:請參閱這裏的「排隊」:http://redis.io/topics/transactions – 2014-09-22 16:16:01