我在我的应用程序中遇到了一个“幽灵”问题,在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页面上,我发现了以下Bug报告:615。
其中写道:
无论Dapper正在发生什么,取消命令时肯定存在竞态条件。部分原因是由于PostgreSQL本身的设计:取消请求是完全"异步"的(它们通过一个不相关的套接字传递,而不是作为要取消的连接的一部分),你不能限制取消只在特定命令执行时生效。换句话说,如果你想取消A命令,在你的取消请求被传送到服务器之前,B命令可能已经开始执行并被取消。
虽然Npgsql 3.0.2已经进行了“更改以使取消更加安全”的修改,但我的当前代码与此版本不兼容,因为需要进行描述 here的迁移。
我的当前解决方法(比较愚蠢):我已经注释了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
Dispose
的一部分中发送取消语句是可怕的。说真的?那只是一个错误,简单明了。快跑,远离那段代码。你应该向ORM开发人员报告错误...然后最好找到一个更合理的。 - Craig Ringer