2015-09-17 2 views
3

У меня есть эта проблема phantom Проблема в моем приложении, где каждый запрос на каждую страницу (в приложении ASP.NET MVC) вызывает эту ошибку:«ОШИБКА: 57014: отмена заявления по запросу пользователя» Npgsql

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

Он говорит, что:

Regardless of what exactly is happening with Dapper, there's definitely a race condition when cancelling commands. Part of this is by design, because of PostgreSQL: cancel requests are totally "asynchronous" (they're delivered via an unrelated socket, not as part of the connection to be cancelled), and you can't restrict the cancellation to take effect only on a specific command. In other words, if you want to cancel command A, by the time your cancellation is delivered command B may already be in progress and it will be cancelled instead.

Несмотря на то, что они сделали «изменения надежно сделают отмену более безопасными» в 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

+0

Почему вы выполняете запрос в первую очередь? Какую проблему вы пытаетесь решить, сделав это? –

+0

@CraigRinger Этот код является частью Micro ORM, который я использую - Dapper. Это часть метода Dispose. Я думаю, что читатель не закрывается должным образом, и это является причиной вызова команды.Cancel(). Исходный код можно найти здесь https://github.com/StackExchange/dapper-dot-net/blob/master/Dapper%20NET40/SqlMapper.cs#L4497 – gyosifov

+0

Отправка заявления отменить, поскольку часть 'Dispose' ужасна. Шутки в сторону? Это просто ошибка, простая и простая. Бегите, не ходите, далеко от этого кода. Вы должны сообщить об ошибке разработчикам ORM ... тогда желательно найти более здравый вариант. –

ответ

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; 
} 

To:

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() не вызывается.

Надеюсь, это поможет кому угодно!

UPDATE

В npgsql docs for version 2.2 состояния:

Npgsql is able to ask the server to cancel commands in progress. To do this, call the NpgsqlCommand’s Cancel method. Note that another thread must handle the request as the main thread will be blocked waiting for command to finish. Also, the main thread will raise an exception as a result of user cancellation. (The error code is 57014.)

Я также разместил issue на Dapper странице GitHub.

+1

Мы столкнулись с этой проблемой при неправильном использовании Dapper. В частности, это было потому, что мы делали команды INSERT/UPDATE/DELETE с Query вместо Execute. Я думаю, что другие провайдеры меня более терпимы к такого рода злоупотреблениям. –