"ERROR: 57014: canceling statement due to user request" Npgsql



我在我的应用程序中有这个幻影问题,其中每5个请求中就有一个在特定页面上(在ASP上)。. NET MVC应用程序)抛出此错误:

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)
   ...

在npgsql github页面上我发现了以下错误报告:615

上面写着:

不管Dapper到底发生了什么,有取消命令时绝对是竞争条件。部分原因是根据设计,由于PostgreSQL:完全取消请求"异步"(它们通过不相关的套接字传递,而不是作为组件(要取消的连接),并且不能限制取消仅对特定命令生效。在其他单词,如果你想取消命令A,在你取消的时候B命令可能已经在执行中了取消。

尽管他们在Npgsql 3.0.2中做了"希望使取消更安全的更改",但我目前的代码与这个版本不兼容,因为这里描述了迁移的需要。

我目前的解决方案(愚蠢):我已经在Dapper中注释了代码,说command.Cancel();,问题似乎消失了。

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

这个问题有更好的解决办法吗?其次,我在当前修复中失去了什么(除了每次更新Dapper时我都必须记住更改)?

配置:NET45,2.2.5 Npgsql),Postgresql 9.3

我发现了为什么我的代码没有处理读取器,导致调用command.Cancel()。这只发生在QueryMultiple方法中,当不是每个refcursor都被读取时。

更改代码
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;
}

这修复了这个问题,现在阅读器被正确地处理了,command.Cancel()没有被调用。

希望这对其他人有所帮助!

2.2版本的npgsql文档说明:

Npgsql能够请求服务器取消正在进行的命令。要做此时,调用NpgsqlCommand的Cancel方法。注意,另一个线程必须处理请求时,主线程会被阻塞等待吗命令完成。此外,主线程将引发异常用户取消结果。(错误码为57014)

我还在Dapper github页面上发布了一个问题。

最新更新