Peta poco - ExecuteReader需要一个开放且可用的连接

时间:2016-01-06 10:46:39

标签: database exception petapoco

在极少数情况下,我遇到petapoco的一些问题。

有时我会遇到以下异常:

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%)

我使用的是petapoco 5.0.1版。

谢谢! :)

修改

我使用以下构造函数来实例化数据库:

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 个答案:

答案 0 :(得分:1)

当我第一次阅读帖子时,我认为是一个线程错误。但是,我并不是简单地想把它写下来,没有解释。仅供参考,任何在Web应用程序中不一致的错误都很可能是一个线程错误。

好的,为什么它是一个线程错误。您使用PetaPoco作为单例实例,这意味着整个应用程序的一个实例。它主要是因为PetaPoco有内部智能知道何时打开/关闭共享连接,而且运气本身,PetaPoco的使用不会发生碰撞,除了2-3%的时间。

此外,还有一个内部计数器(智能),零时将根据操作创建新连接或关闭现有连接。现在假设PetaPoco不是线程安全的,如果两个或多个线程同时增加/减少计数器等,这个内部计数器也会遇到与线程相关的问题。

TDLR; 在dotnet中,一般规则是假设/使静态方法是线程安全的,其他一切都不是线程安全的,除非有清楚标记的地方和有意义的地方。如果PetaPoco是线程安全的,那么你对PetaPoco的使用会起作用,但事实并非如此。要解决此问题,请为每个请求创建一个新的PetaPoco实例;一个相当便宜的操作(更流畅的配置)。

我看到你正在使用PetaPoco 5.0.1,我建议查看最新版本,因为有一个新的FluentConfiguration功能。事实恰恰相反,该功能的文档页面位于页面底部,具有样本容器设置。我建议你看一下。 Documentation

Happy PetaPoco'er'ing