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