This is a migrated thread and some comments may be shown as answers.

Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool.

3 Answers 695 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Mark
Top achievements
Rank 1
Mark asked on 09 Mar 2015, 04:13 PM
Since upgrading a solution to use Visual Studio 2013 yesterday I'm getting the following error when trying to access the Connection property of a DataContext object not long after launching the application - the application may load the first page (sometimes the exception is thrown before a page loads) but then shortly this exception is thrown.  

The application is still targeting the .NET 4.0 framework and the application works perfectly in VS 2010.  Is there something I need to do in order to get the application to work with IIS Express in VS 2013?

"An exception of type 'Telerik.OpenAccess.OpenAccessException' occurred in Telerik.OpenAccess.dll but was not handled in user code

Additional information: System.InvalidOperationException: Timeout expired.  The timeout period elapsed prior to obtaining a connection from the pool.  This may have occurred because all pooled connections were in use and max pool size was reached.

   at Telerik.OpenAccess.RT.Adonet2Generic.Impl.DBDriver.connect(ConnectionString connectionString, PropertySet driverProps, ConnectionPoolType poolType, LogEventStore pes)

   at OpenAccessRuntime.Relational.conn.RelationalConnectionPool.createRealCon()

   at OpenAccessRuntime.Relational.conn.RelationalConnectionPool.CreatePlainAdoConnection()

   at OpenAccessRuntime.Relational.conn.RelationalConnectionPool.getConnection(Boolean highPriority, Boolean autoCommit, Int32 smId)

   at OpenAccessRuntime.Relational.RelationalStorageManager.obtainConnection(Boolean forWriting)"

The following method is where the exception is being thrown.  I am manipulating the connection string because there is a requirement to be able to change the store name dynamically and on the fly:

public static string GetConnectionString<DC>(bool extendedTimeout, bool storeOverride, string storeName)
            where DC : OpenAccessContext
        {
            string connectionString = string.Empty;

            int timeoutTarget = DataSettings.ConnectionTimeoutDefault;
            if (extendedTimeout)
            {
                timeoutTarget = DataSettings.ConnectionTimeoutExtended;
            }

            OpenAccessContext dataContext = Activator.CreateInstance<DC>();

            bool correctTimeout = true;
            if (dataContext != null)
            {
                if (dataContext.Connection.ConnectionTimeout != timeoutTarget)  // this is where the exception is thrown
                {
                    correctTimeout = false;
                }
            }
            else
            {
                correctTimeout = false;
            }

            if (dataContext != null)
            {
                string currentConnectionString = dataContext.Connection.ConnectionString;
                if (!string.IsNullOrWhiteSpace(currentConnectionString))
                {
                    SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(currentConnectionString);

                    if (correctTimeout == false)
                    {
                        connectionStringBuilder.ConnectTimeout = timeoutTarget;
                    }

                    if (storeOverride == true)
                    {
                        if (!string.IsNullOrWhiteSpace(storeName))
                        {                            
                            connectionStringBuilder.InitialCatalog = storeName;
                        }
                        else
                        {
                            connectionStringBuilder.InitialCatalog = "InvalidStoreName";
                        }
                    }

                    connectionStringBuilder.MultipleActiveResultSets = false;
                    connectionStringBuilder.ContextConnection = false;

                    try
                    {
                        connectionString = connectionStringBuilder.ConnectionString;
                    }
                    catch (Exception ex)
                    {
                        connectionString = ex.Message;

                        // TODO: Log exception...
                    }
                }
            }

            return connectionString;
        }

3 Answers, 1 is accepted

Sort by
0
Mark
Top achievements
Rank 1
answered on 09 Mar 2015, 04:18 PM
Having initially logged a support ticket for this the support team followed up with this response:

Essentially they are saying the accessing the Connection property fires up a new connection that isn't disposed.  How are you supposed to access, for example: 
dataContext.Connection.ConnectionTimeout
and dispose of the connection when you're done?

"Hi Mark,

Thank you for the feedback and for the additional details.

Following is further information about the error and two suggestions for implementing the scenario you describe.

Regarding the error, the provided code snippet calls the Connection properties on three occasions, which means three different connections: 
here,
using (dataContext.Connection)
here,
if (dataContext.Connection.ConnectionTimeout != timeoutTarget)
and here
string currentConnectionString = dataContext.Connection.ConnectionString;

In the first case, the connection is properly closed and disposed. In the other two cases the created connections are leaked. 

During runtime, when the app goes through the code from the second and third cases, the two different newly created (or taken from the pool) connections are never closed. This means that although the exception happens for the code from the first case, the cause for it is that the other two calls to the Connection property exhausted the pool (the default pool size is 10 and when the connections are already leaked there is no connection for this code). 

Regarding the scenario, one of the options is to use the Connect Timeout attribute in the connection string and to code a convenient value in seconds. For example:
<add name="ProjectManagementConnection"
   connectionString="Data Source=.\SQLEXPRESS;
              Initial Catalog=ProjectManagement;
              Integrated Security=True;
              Connect Timeout=20;
              User Instance=False" 
   providerName="System.Data.SqlClient" />
</connectionStrings>
The other option is to use the ConfigurationManager and WebConfigurationManager classes (instead of accessing the context), in order to access, modify, and preserve the connection strings in the .config files. Both of them expose a ConnectionStrings property in which you can find the specific values."

0
Mark
Top achievements
Rank 1
answered on 09 Mar 2015, 04:19 PM
I also don't understand, above all, why this works just fine in VS 2010 and when deployed to our servers.
0
Doroteya
Telerik team
answered on 13 Mar 2015, 08:23 AM
Hi Mark,

Based on our our communication in the support thread, following are the answers to your questions:

Regarding the access of the connection properties, you could assign the connection to a variable and use it like this:
using (OAConnection myConnection = dbContext.Connection)
{
    if(myConnection.ConnectionTimeout != timeoutTarget)
      {
          //TODO: the relevant logic comes here
      }
}
Note that the OAConnection class is in the Telerik.OpenAccess.Data.Common namespace.

Regarding the migration of the solution to Visual Studio 2013, let me confirm that in Data Access the particular connection handling behaviour I outlined is the one with which the product is originally designed. My best guess about the cause of the difference on your side will be that during the migration a setting like the Maximum Connections Used number or the type of the connection pool was lost.

I hope this helps. Do let us know how the things on your side are.


Regards,
Doroteya
Telerik
 
OpenAccess ORM is now Telerik Data Access. For more information on the new names, please, check out the Telerik Product Map.
 
Tags
General Discussions
Asked by
Mark
Top achievements
Rank 1
Answers by
Mark
Top achievements
Rank 1
Doroteya
Telerik team
Share this question
or