internal override async Task <StorageSession> TryAdaptTransportConnection(TransportTransaction transportTransaction, ContextBag context, IConnectionManager connectionBuilder, Func <DbConnection, DbTransaction, bool, StorageSession> storageSessionFactory) { // Transport supports DTC and uses TxScope owned by the transport var scopeTx = Transaction.Current; if (transportTransaction.TryGet(out Transaction transportTx) && scopeTx != null && transportTx != scopeTx) { throw new Exception("A TransactionScope has been opened in the current context overriding the one created by the transport. " + "This setup can result in inconsistent data because operations done via connections enlisted in the context scope won't be committed " + "atomically with the receive transaction. To manually control the TransactionScope in the pipeline switch the transport transaction mode " + $"to values lower than '{nameof(TransportTransactionMode.TransactionScope)}'."); } var ambientTransaction = transportTx ?? scopeTx; if (ambientTransaction == null) { //Other modes handled by creating a new session. return(null); } var connection = await connectionBuilder.OpenConnection(context.GetIncomingMessage()).ConfigureAwait(false); connection.EnlistTransaction(ambientTransaction); return(storageSessionFactory(connection, null, true)); }
public async Task <OutboxTransaction> BeginTransaction(ContextBag context) { var connection = await connectionManager.OpenConnection(context.GetIncomingMessage()).ConfigureAwait(false); var transaction = connection.BeginTransaction(); return(new SqlOutboxTransaction(transaction, connection)); }
public async Task <CompletableSynchronizedStorageSession> OpenSession(ContextBag contextBag) { var connection = await connectionManager.OpenConnection(contextBag.GetIncomingMessage()).ConfigureAwait(false); var transaction = connection.BeginTransaction(); return(new StorageSession(connection, transaction, true, infoCache)); }
public async Task Begin(ContextBag context) { var incomingMessage = context.GetIncomingMessage(); Connection = await connectionManager.OpenConnection(incomingMessage).ConfigureAwait(false); Transaction = Connection.BeginTransaction(); await concurrencyControlStrategy.Begin(incomingMessage.MessageId, Connection, Transaction).ConfigureAwait(false); }
public async Task Begin(ContextBag context, CancellationToken cancellationToken = default) { var incomingMessage = context.GetIncomingMessage(); Connection = await connectionManager.OpenConnection(incomingMessage, cancellationToken).ConfigureAwait(false); Connection.EnlistTransaction(ambientTransaction); await concurrencyControlStrategy.Begin(incomingMessage.MessageId, Connection, null, cancellationToken).ConfigureAwait(false); }
public async Task <CompletableSynchronizedStorageSession> OpenSession(ContextBag contextBag, CancellationToken cancellationToken = default) { var connection = await connectionManager.OpenConnection(contextBag.GetIncomingMessage(), cancellationToken).ConfigureAwait(false); var transaction = connection.BeginTransaction(); var session = new StorageSession(connection, transaction, true, infoCache); currentSessionHolder?.SetCurrentSession(session); return(session); }
public async Task SetAsDispatched(string messageId, ContextBag context) { using (var connection = await connectionManager.OpenConnection(context.GetIncomingMessage()).ConfigureAwait(false)) using (var command = sqlDialect.CreateCommand(connection)) { command.CommandText = outboxCommands.SetAsDispatched; command.AddParameter("MessageId", messageId); command.AddParameter("DispatchedAt", DateTime.UtcNow); await command.ExecuteNonQueryEx().ConfigureAwait(false); } }
public async Task Begin(ContextBag context) { transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew, TransactionScopeAsyncFlowOption.Enabled); ambientTransaction = System.Transactions.Transaction.Current; var incomingMessage = context.GetIncomingMessage(); Connection = await connectionManager.OpenConnection(incomingMessage).ConfigureAwait(false); Connection.EnlistTransaction(ambientTransaction); await concurrencyControlStrategy.Begin(incomingMessage.MessageId, Connection, null).ConfigureAwait(false); }
public async Task <OutboxMessage> Get(string messageId, ContextBag context, CancellationToken cancellationToken = default) { using (new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled)) using (var connection = await connectionManager.OpenConnection(context.GetIncomingMessage(), cancellationToken).ConfigureAwait(false)) using (var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted)) { OutboxMessage result; using (var command = sqlDialect.CreateCommand(connection)) { command.CommandText = outboxCommands.Get; command.Transaction = transaction; command.AddParameter("MessageId", messageId); // to avoid loading into memory SequentialAccess is required which means each fields needs to be accessed, but SequentialAccess is unsupported for SQL Server AlwaysEncrypted using (var dataReader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess | CommandBehavior.SingleRow, cancellationToken).ConfigureAwait(false)) { if (!await dataReader.ReadAsync(cancellationToken).ConfigureAwait(false)) { return(null); } var dispatched = await dataReader.GetBoolAsync(0, cancellationToken).ConfigureAwait(false); using (var textReader = dataReader.GetTextReader(1)) { if (dispatched) { result = new OutboxMessage(messageId, new TransportOperation[0]); } else { var transportOperations = Serializer.Deserialize <IEnumerable <SerializableOperation> >(textReader) .FromSerializable() .ToArray(); result = new OutboxMessage(messageId, transportOperations); } } } } transaction.Commit(); return(result); } }