Как вы правильно заметили, версия Rebus >= 0.90.0 не включается автоматически во внешние транзакции.
(ОБНОВЛЕНИЕ: начиная с 0.99.16 желаемое поведение может быть достигнуто - см. Конец этого ответа для получения подробной информации о том, как)
Однако это не означает, что Rebus не может участвовать в транзакции — он просто использует собственный механизм внешней транзакции (который не зависит от System.Transactions
и будет доступен, когда Rebus будет портирован на ядро .NET).
Вы можете использовать DefaultTransactionContext
Ребуса и "сделать его эмбиентным" с этим AmbientRebusTransactionContext
:
/// <summary>
/// Rebus ambient transaction scope helper
/// </summary>
public class AmbientRebusTransactionContext : IDisposable
{
readonly DefaultTransactionContext _transactionContext = new DefaultTransactionContext();
public AmbientRebusTransactionContext()
{
if (AmbientTransactionContext.Current != null)
{
throw new InvalidOperationException("Cannot start a Rebus transaction because one was already active!");
}
AmbientTransactionContext.Current = _transactionContext;
}
public Task Complete()
{
return _transactionContext.Complete();
}
public void Dispose()
{
AmbientTransactionContext.Current = null;
}
}
который вы затем можете использовать следующим образом:
using(var tx = new AmbientRebusTransactionContext())
{
await bus.Send(new Message());
await tx.Complete();
}
или, если вы используете его в веб-приложении, я предлагаю вам обернуть его промежуточным программным обеспечением OWIN следующим образом:
app.Use(async (context, next) =>
{
using (var transactionContext = new AmbientRebusTransactionContext())
{
await next();
await transactionContext.Complete();
}
});
ОБНОВЛЕНИЕ. Начиная с версии Rebus 0.99.16 поддерживается следующее (через пакет Rebus.TransactionScope
):
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
scope.EnlistRebus(); //< enlist Rebus in ambient .NET tx
await _bus.SendLocal("hallå i stuen!1");
scope.Complete();
}
person
mookid8000
schedule
27.11.2015