63 votes

Valider ou annuler de manière asynchrone une étendue de transaction

Comme beaucoup le sait, TransactionScope ont été oubliés lors de l' async await modèle a été introduit en .Net. Ils ont rompu si nous avons essayé d'utiliser certains await appel à l'intérieur d'une étendue de transaction.

Maintenant ce problème est résolu grâce à une portée constructeur option.

Mais il me semble il y a toujours une pièce manquante, au moins, je suis incapable de trouver comment le faire en un simple "étendue de la transaction comme" manière: comment faire pour attendre la validation ou annulation d'une portée?

Commit et rollback sont des opérations d'e / s trop, ils devraient être awaitable. Mais depuis qu'ils se produisent sur la portée de la disposition, on devra attendre le jeter. Qui n'a pas l'air faisable (ni pratique avec l' using des motifs).

J'ai eu un coup d'oeil à l' System.Transactions.Transaction interface aussi: pas de awaitable méthodes il soit.

Je comprends que le fait de commettre et le retour arrière est presque uniquement de l'envoi d'un drapeau à la base de données, donc ça devrait être rapide. Mais avec des transactions distribuées, qui pourrait être moins rapide. Et de toute façon, c'est toujours un certain blocage IO.

Distribué cas, rappelez-vous ce qui pourrait déclencher une deux phases commit. Dans certains cas, d'autres durable des ressources sont enrôlés au cours de la première phase (préparer). Ensuite, il signifie généralement que quelques autres requêtes sont émises à l'encontre de ceux qui, dernièrement, s'est enrôlé ressources. Tout ce qui se passe lors de la validation.

Donc, est-il possible d'attendre une étendue de transaction? Ou un System.Transactions.Transaction à la place?

Note: je ne considère pas cela comme un doublon de "Est-il possible de commit/rollback SqlTransaction asynchrone?". SqlTransaction sont plus limités que les transactions du système. Ils peuvent s'adresser uniquement SQL-Server et ne sont jamais distribués. Certaines autres transactions n'ont de méthodes asynchrones, comme Npgsql. Maintenant, pour avoir des méthodes asynchrones sur des transactions étendues/système de transactions, DbTransaction peut être nécessaire de disposer de méthodes asynchrones. (Je ne connais pas le fonctionnement interne du système de transaction, mais il est peut-être à l'aide de cette ADO.NET contrat. La façon dont nous inscrire dans le système de transaction ne me laisse penser qu'il ne l'utilise pas bien.)

0voto

felix-b Points 4017

Peut-être une réponse tardive, mais ce que vous voulez, fondamentalement, se résume à une sorte de sucre syntaxique qui peut être créé facilement sur votre propre.

La généralisation votre problème, j'ai mis en place un "asynchrone à l'aide de la syntaxe, qui permet à la fois le corps et le "jeter" une partie de l ' "utilisation" d'être awaitable. Voici à quoi il ressemble:

async Task DoSomething()
{ 
    await UsingAsync.Do(
        // this is the disposable usually passed to using(...)
        new TransactionScope(TransactionScopeAsyncFlowOption.Enabled), 
        // this is the body of the using() {...}
        async transaction => {
            await Task.Delay(100);   // do any async stuff here...
            transaction.Complete();  // mark transaction for Commit
        } // <-- the "dispose" part is also awaitable
    );
}

La mise en œuvre est aussi simple que cela:

public static class UsingAsync
{
    public static async Task Do<TDisposable>(
        TDisposable disposable, 
        Func<TDisposable, Task> body)
        where TDisposable : IDisposable
    {
        try
        {
            await body(disposable);
        }
        finally
        {
            if (disposable != null)
            {
                await Task.Run(() => disposable.Dispose());
            }
        }
    }
}

Il y a une différence dans la gestion d'erreur, par rapport à la régulière, using de la clause. Lors de l'utilisation d' UsingAsync.Do, toute exception levée par l'organisme ou de l'aliéner sera enroulé à l'intérieur d'un AggregateException. Ceci est utile lorsque les deux corps et disposer chaque lancer une exception, et les deux exceptions peuvent être examinés dans un AggregateException. Avec la régularité using clause, seul l'exception levée par disposer d'être pris, à moins que le corps est explicitement enveloppé dans try..catch.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X