"ERROR: 57014: annulation de l'instruction en raison de la demande de l'utilisateur" Npgsql

command dapper npgsql postgresql

Question

J'ai ce problème fantôme dans mon application où une requête sur 5 sur une page spécifique (sur une application ASP.NET MVC) génère cette erreur:

Npgsql.NpgsqlException: ERROR: 57014: canceling statement due to user request
   at Npgsql.NpgsqlState.<ProcessBackendResponses>d__0.MoveNext()
   at Npgsql.ForwardsOnlyDataReader.GetNextResponseObject(Boolean cleanup)
   at Npgsql.ForwardsOnlyDataReader.GetNextRow(Boolean clearPending)
   at Npgsql.ForwardsOnlyDataReader.Read()
   at Npgsql.NpgsqlCommand.GetReader(CommandBehavior cb)
   ...

Sur la page github npgsql, j'ai trouvé le rapport de bogue suivant: 615

Il y est dit:

Indépendamment de ce qui se passe exactement avec Dapper, il y a certainement une condition de course lors de l'annulation des commandes. Cela est dû en partie à la conception, car PostgreSQL ™: les requêtes d'annulation sont totalement "asynchrones" (elles sont délivrées via une socket non associée, et non dans le cadre de la connexion à annuler), et vous ne pouvez pas limiter l'annulation. uniquement sur une commande spécifique. En d'autres termes, si vous souhaitez annuler la commande A, au moment où votre annulation est délivrée, la commande B est peut-être déjà en cours et sera annulée à la place.

Bien qu'ils aient fait des "modifications pour rendre les annulations plus sûres" dans Npgsql 3.0.2, mon code actuel est incompatible avec cette version car le besoin de migration est décrit ici .

Mon contournement actuel (stupide) : J'ai commenté le code dans Dapper qui dit commande.Cancel command.Cancel(); et le problème semble avoir disparu.

if (reader != null)
                {
                    if (!reader.IsClosed && command != null)
                    {
                        //command.Cancel();
                    }
                    reader.Dispose();
                    reader = null;
                }

Y a-t-il une meilleure solution au problème? Et deuxièmement, qu'est-ce que je perds avec le correctif actuel (sauf que je dois me souvenir du changement chaque fois que je mets à jour Dapper)?

Configuration: NET45, Npgsql 2.2.5, Postgresql 9.3

Réponse acceptée

J'ai trouvé pourquoi mon code ne disposait pas du lecteur, entraînant l'appel de command.Cancel() . Cela se produit uniquement avec la méthode QueryMultiple lorsque tous les refcursor ne sont pas lus.

Changer le code de:

using (var multipleResults = connection.QueryMultiple("schema.getuserbysocialsecurity", new { socialSecurityNumber }))
{
    var client = multipleResults.Read<Client>().SingleOrDefault();

    if (client != null)
    {
        client.Address = multipleResults.Read<Address>().Single();
    }

    return client;
}

À:

using (var multipleResults = connection.QueryMultiple("schema.getuserbysocialsecurity", new { socialSecurityNumber }))
{
    var client = multipleResults.Read<Client>().SingleOrDefault();
    var address = multipleResults.Read<Address>().SingleOrDefault();

    if (client != null)
    {
        client.Address = address;
    }

    return client;
}

Cela a résolu le problème et maintenant le lecteur est correctement disposé et command.Cancel() n'est pas invoqué.

J'espère que cela aide quelqu'un d'autre!

METTRE À JOUR

Le document npgsql docs pour la version 2.2 indique:

Npgsql est en mesure de demander au serveur d’annuler les commandes en cours. Pour ce faire, appelez la méthode Cancel de NpgsqlCommand. Notez qu'un autre thread doit gérer la requête car le thread principal sera bloqué en attendant que la commande se termine. En outre, le thread principal générera une exception suite à l'annulation de l'utilisateur. (Le code d'erreur est 57014.)

J'ai également posté un problème sur la page github de Dapper.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi