Peta Poco - ExecuteReader требует открытого и доступного соединения

В редких ситуациях у меня возникают проблемы с петапоко.

Иногда я получаю следующее исключение:

System.InvalidOperationException: ExecuteReader requires an open and available Connection. The connection's current state is connecting.
   at System.Data.SqlClient.SqlConnection.GetOpenConnection(String method)
   at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command)
   at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader()
   at PetaPoco.Database.<Query>d__44`1.MoveNext()

Я действительно не знаю, что с этим делать. Кто-нибудь видел это раньше? Любые предложения о том, почему это происходит и что с этим делать?

Я не могу воспроизвести его, так как это происходит редко (может быть, 2-3% вызовов БД)

Я использую версию 5.0.1 petapoco.

Спасибо!:)

РЕДАКТИРОВАТЬ:

Я использую следующий конструктор для создания экземпляра базы данных:

public Database(string connectionString, string providerName)
{
    _connectionString = connectionString;
    _providerName = providerName;
    CommonConstruct();
}

Я создаю его как синглтон, используя внедрение зависимости, как показано ниже:

Container.Register(Component.For<IDatabase>().ImplementedBy<Database>().UsingFactoryMethod(() => new Database(configuration.ConnectionString, configuration.DbFactoryProvider)).LifestyleSingleton());

1 ответ

Решение

Когда я впервые прочитал этот пост, я подумал, что это жуткая ошибка. Однако я просто не хотел списывать это без объяснения причин. К вашему сведению, любая ошибка, подобная этой, в веб-приложении, скорее всего, является ошибкой многопоточности.

Хорошо, так почему это ошибка с потоками. Вы используете PetaPoco как одноэлементный экземпляр, что означает один экземпляр для всего приложения. Это работает, главным образом, потому что PetaPoco имеет внутренние умения знать, когда открывать / закрывать общее соединение, и просто по счастливой случайности использование PetaPoco не сталкивается, за исключением 2-3% времени.

Кроме того, есть внутренний счетчик (smarts), который, когда ноль, создаст новое соединение или закроет существующее в зависимости от операции. Теперь, учитывая, что PetaPoco не является потокобезопасным, этот внутренний счетчик также может страдать из-за проблем, связанных с потоками, если два или более потоков увеличивают / уменьшают счетчик одновременно и т. Д.

TDLR; В dotnet общее правило состоит в том, чтобы предполагать / делать статические методы поточно-ориентированными, а все остальное - не потоко-безопасными, за исключением случаев, когда они четко обозначены и где это имеет смысл. Ваше использование PetaPoco будет работать, если PetaPoco является поточно-ориентированным, но это не так. Чтобы решить эту проблему, создайте новый экземпляр PetaPoco для каждого запроса; довольно дешевая операция (более того с быстрой конфигурацией).

Я вижу, что вы используете PetaPoco 5.0.1, предлагаю взглянуть на последнюю версию, так как есть новая функция FluentConfiguration. И так уж получилось, что на странице документации по этой функции внизу страницы есть образец настройки контейнера. Я бы посоветовал вам проверить это. Документация

Happy PetaPoco'er'ing

Другие вопросы по тегам