我在我的应用程序中有这个幻影问题,其中每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页面上发布了一个问题。