c# .net .net-4.0 async-await transactionscope

c# - ¿Cómo admitir los métodos asíncronos en un TransactionScope con Microsoft.Bcl.Async en.NET 4.0?



.net-4.0 async-await (2)

Tengo un método similar a:

public async Task SaveItemsAsync(IEnumerable<MyItem> items) { using (var ts = new TransactionScope()) { foreach (var item in items) { await _repository.SaveItemAsync(item); } await _repository.DoSomethingElse(); ts.Complete(); } }

Por supuesto, esto tiene problemas porque TransactionScope no funciona bien con async / await.

Falla con una InvalidOperationException con el mensaje:

"Un TransactionScope debe estar dispuesto en el mismo hilo que se creó".

Leí sobre TransactionScopeAsyncFlowOption en esta respuesta , que parece ser exactamente lo que necesito.

Sin embargo, para este proyecto en particular, tengo un gran requisito para admitir .Net 4.0 y no puedo actualizar a 4.5 o 4.5.1. Por lo tanto, el comportamiento de async / await en mi proyecto lo proporciona el paquete Microsoft.Bcl.Async NuGet .

Parece que no puedo encontrar TransactionScopeAsyncFlowOption en este o cualquier otro paquete OOB . ¿Me estoy perdiendo en alguna parte?

Si no está disponible, ¿hay alguna alternativa para lograr el mismo resultado? Es decir, me gustaría que el alcance de la transacción se complete o retroceda correctamente, a pesar de cruzar hilos con continuaciones.

DoSomethingElse en el ejemplo anterior para ilustrar que puede haber múltiples llamadas dentro del alcance de la transacción, por lo que simplemente pasar todos los elementos a la base de datos en una llamada no es una opción viable.

En caso de que sea importante, el repositorio utiliza ADO.Net directo ( SqlConnection , SqlCommand , etc.) para escribir en un servidor SQL.

ACTUALIZAR

Pensé que tenía una solución que implicaba tomar System.Transactions.dll de .Net 4.5.1 e incluirla en mi proyecto. Sin embargo, encontré que esto funcionaba solo en mi caja de desarrollo porque ya tenía 4.5.1 instalado. No funcionó cuando se implementaba en una máquina solo con .Net 4.0. Acaba de dar una MissingMethodException . Estoy buscando una solución que funcione en una instalación .Net 4.0.


No estoy seguro de si esto se ajusta a su situación, pero ConfigureAwait(false) se puede usar en una aplicación ASP.NET para asegurarse de que una llamada de función esperada vuelva a entrar en el contexto de solicitud de llamada.

Entonces, si este código se ejecuta en una aplicación ASP.NET, el siguiente código:

await _repository.SaveItemAsync(item).ConfigureAwait(false);

Aseguraría que la ejecución continuaría en el hilo de solicitud.


Tienes que usar TransactionScopeAsyncFlowOption.Enabled

public static TransactionScope CreateAsyncTransactionScope(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) { var transactionOptions = new TransactionOptions { IsolationLevel = isolationLevel, Timeout = TransactionManager.MaximumTimeout }; return new TransactionScope(TransactionScopeOption.Required, transactionOptions, TransactionScopeAsyncFlowOption.Enabled); }