"错误:57014:由于用户请求而取消声明" Npgsql的

时间:2015-09-17 14:30:21

标签: postgresql command dapper npgsql

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

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:完全取消请求   &#34;异步&#34; (他们通过一个不相关的套接字,而不是作为一部分   要取消的连接),你不能限制   取消仅对特定命令生效。其他   单词,如果要在取消时取消命令A.   已发送命令B可能已在进行中,它将是   取而代之的是。

虽然他们已经进行了&#34;更改,希望在Npgsql 3.0.2中使取消更加安全&#34; 我的当前代码与此版本不兼容,因为需要迁移描述{{3 }}

我当前的解决方法(愚蠢):我已经在Dapper中对command.Cancel();的代码进行了评论,问题似乎已经消失。

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

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

配置: NET45, Npgsql 2.2.5, Postgresql 9.3

1 个答案:

答案 0 :(得分:0)

我发现为什么我的代码没有处理读者,导致调用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()

希望这有助于其他任何人!

<强>更新

npgsql docs for version 2.2州:

  

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

我还在Dapper github页面上发布了issue