Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature | Add "Command Timeout" connection string property #722

Merged
merged 7 commits into from
Sep 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,7 @@ For example, with a 30 second time out, if <xref:Microsoft.Data.SqlClient.SqlDat
[!code-csharp[SqlCommand CommandTimeout](~/../sqlclient/doc/samples/SqlCommand_CommandTimeout.cs)]
]]></format>
</remarks>
<exception cref="T:System.ArgumentException">The value set is less than 0.</exception>
</CommandTimeout>
<CommandType>
<summary>
Expand Down
18 changes: 18 additions & 0 deletions doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,23 @@ The connection string contains <see langword="Context Connection=true" />.
<value>The list of trusted master key paths for the column encryption.</value>
<remarks>To be added.</remarks>
</ColumnEncryptionTrustedMasterKeyPaths>
<CommandTimeout>
<summary>
Gets the default wait time (in seconds) before terminating the attempt to execute a command and generating an error. The default is 30 seconds.
</summary>
<value>
The time in seconds to wait for the command to execute. The default is 30 seconds.
</value>
<remarks>
<format type="text/markdown"><![CDATA[

## Remarks

You can set the default wait time by using the `Command Timeout` keyword in the connection string. A value of 0 indicates no limit (an attempt to execute a command will wait indefinitely).

]]></format>
</remarks>
</CommandTimeout>
<ConnectionString>
<summary>Gets or sets the string used to open a SQL Server database.</summary>
<value>The connection string that includes the source database name, and other parameters needed to establish the initial connection. The default value is an empty string.</value>
Expand Down Expand Up @@ -517,6 +534,7 @@ The connection string contains <see langword="Context Connection=true" />.
|AttachDBFilename<br /><br /> -or-<br /><br /> Extended Properties<br /><br /> -or-<br /><br /> Initial File Name|N/A|The name of the primary database file, including the full path name of an attachable database. AttachDBFilename is only supported for primary data files with an .mdf extension.<br /><br /> If the value of the AttachDBFileName key is specified in the connection string, the database is attached and becomes the default database for the connection.<br /><br /> If this key is not specified and if the database was previously attached, the database will not be reattached. The previously attached database will be used as the default database for the connection.<br /><br /> If this key is specified together with the AttachDBFileName key, the value of this key will be used as the alias. However, if the name is already used in another attached database, the connection will fail.<br /><br /> The path may be absolute or relative by using the DataDirectory substitution string. If DataDirectory is used, the database file must exist within a subdirectory of the directory pointed to by the substitution string. **Note:** Remote server, HTTP, and UNC path names are not supported. <br /><br /> The database name must be specified with the keyword 'database' (or one of its aliases) as in the following:<br /><br /> <code>"AttachDbFileName=&#124;DataDirectory&#124;\data\YourDB.mdf;integrated security=true;database=YourDatabase"</code><br /><br /> An error will be generated if a log file exists in the same directory as the data file and the 'database' keyword is used when attaching the primary data file. In this case, remove the log file. Once the database is attached, a new log file will be automatically generated based on the physical path.|
|Authentication|N/A|The authentication method used for [Connecting to SQL Database By Using Azure Active Directory Authentication](https://azure.microsoft.com/documentation/articles/sql-database-aad-authentication/#7-connect-to-your-database-by-using-azure-active-directory-identities).<br /><br /> Valid values are:<br /><br /> `Active Directory Integrated`, `Active Directory Interactive`, `Active Directory Password`, `Sql Password`. Currently `Active Directory Integrated` and `Active Directory Interactive` modes of authentication are supported only for .NET Framework. |
|Column Encryption Setting|N/A|Enables or disables [Always Encrypted](/sql/relational-databases/security/encryption/always-encrypted-database-engine?view=sql-server-2017) functionality for the connection.|
|Command Timeout|30|The default wait time (in seconds) before terminating the attempt to execute a command and generating an error.<br /><br /> Valid values are greater than or equal to 0 and less than or equal to 2147483647.|
|Connect Timeout<br /><br /> -or-<br /><br /> Connection Timeout<br /><br /> -or-<br /><br /> Timeout|15|The length of time (in seconds) to wait for a connection to the server before terminating the attempt and generating an error.<br /><br /> Valid values are greater than or equal to 0 and less than or equal to 2147483647.<br /><br /> When opening a connection to a Azure SQL Database, set the connection timeout to 30 seconds.|
|Connection Lifetime<br /><br /> -or-<br /><br /> Load Balance Timeout|0|When a connection is returned to the pool, its creation time is compared with the current time, and the connection is destroyed if that time span (in seconds) exceeds the value specified by `Connection Lifetime`. This is useful in clustered configurations to force load balancing between a running server and a server just brought online.<br /><br /> A value of zero (0) causes pooled connections to have the maximum connection timeout.|
|Connect Retry Count<br /><br /> -or-<br /><br />ConnectRetryCount|1|Controls the number of reconnection attempts after the client identifies an idle connection failure. Valid values are 0 to 255. The default is 1. 0 means do not attempt to reconnect (disable connection resiliency).<br /><br /> For additional information about idle connection resiliency, see [Technical Article - Idle Connection Resiliency](https://go.microsoft.com/fwlink/?LinkId=393996).|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,23 @@ Modified: Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security
<value>The column encryption settings for the connection string builder.</value>
<remarks>To be added.</remarks>
</ColumnEncryptionSetting>
<CommandTimeout>
<summary>
The default wait time (in seconds) before terminating the attempt to execute a command and generating an error. The default is 30 seconds.
</summary>
<value>
The time in seconds to wait for the command to execute. The default is 30 seconds.
</value>
<remarks>
<format type="text/markdown"><![CDATA[

## Remarks
This property corresponds to the "Command Timeout" key within the <xref:Microsoft.Data.SqlClient.SqlConnection> connection string.

]]></format>
</remarks>
<exception cref="T:System.ArgumentException">The value set is less than 0.</exception>
</CommandTimeout>
<ConnectionReset>
<summary>Obsolete. Gets or sets a Boolean value that indicates whether the connection is reset when drawn from the connection pool.</summary>
<value>The value of the <see cref="P:Microsoft.Data.SqlClient.SqlConnectionStringBuilder.ConnectionReset" /> property, or true if no value has been supplied.</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,9 @@ public SqlConnection(string connectionString, Microsoft.Data.SqlClient.SqlCreden
internal string SQLDNSCachingSupportedStateBeforeRedirect { get { throw null; } }

object System.ICloneable.Clone() { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/CommandTimeout/*' />
[System.ComponentModel.DesignerSerializationVisibilityAttribute(0)]
public int CommandTimeout { get { throw null; } }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/ConnectionString/*'/>
[System.ComponentModel.DefaultValueAttribute("")]
[System.ComponentModel.EditorAttribute("Microsoft.VSDesigner.Data.SQL.Design.SqlConnectionStringEditor, Microsoft.VSDesigner, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
Expand Down Expand Up @@ -712,6 +715,10 @@ public SqlConnectionStringBuilder(string connectionString) { }
[System.ComponentModel.DisplayNameAttribute("Authentication")]
[System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
public Microsoft.Data.SqlClient.SqlAuthenticationMethod Authentication { get { throw null; } set { } }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml' path='docs/members[@name="SqlConnectionStringBuilder"]/CommandTimeout/*'/>
[System.ComponentModel.DisplayNameAttribute("Command Timeout")]
[System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
public int CommandTimeout { get { throw null; } set { } }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml' path='docs/members[@name="SqlConnectionStringBuilder"]/ConnectRetryCount/*'/>
[System.ComponentModel.DisplayNameAttribute("Connect Retry Count")]
[System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ internal static ApplicationIntent ConvertToApplicationIntent(string keyword, obj

internal static bool IsValidAuthenticationTypeValue(SqlAuthenticationMethod value)
{
Debug.Assert(Enum.GetNames(typeof(SqlAuthenticationMethod)).Length == 6, "SqlAuthenticationMethod enum has changed, update needed");
Debug.Assert(Enum.GetNames(typeof(SqlAuthenticationMethod)).Length == 7, "SqlAuthenticationMethod enum has changed, update needed");
return value == SqlAuthenticationMethod.SqlPassword
|| value == SqlAuthenticationMethod.ActiveDirectoryPassword
|| value == SqlAuthenticationMethod.ActiveDirectoryIntegrated
Expand Down Expand Up @@ -676,6 +676,7 @@ internal static partial class DbConnectionStringDefaults
internal const ApplicationIntent ApplicationIntent = Microsoft.Data.SqlClient.ApplicationIntent.ReadWrite;
internal const string ApplicationName = "Core Microsoft SqlClient Data Provider";
internal const string AttachDBFilename = "";
internal const int CommandTimeout = 30;
internal const int ConnectTimeout = 15;
internal const string CurrentLanguage = "";
internal const string DataSource = "";
Expand Down Expand Up @@ -719,6 +720,7 @@ internal static partial class DbConnectionStringKeywords
internal const string ApplicationName = "Application Name";
internal const string AsynchronousProcessing = "Asynchronous Processing";
internal const string AttachDBFilename = "AttachDbFilename";
internal const string CommandTimeout = "Command Timeout";
internal const string ConnectTimeout = "Connect Timeout";
internal const string ConnectionReset = "Connection Reset";
internal const string ContextConnection = "Context Connection";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ protected override void AfterCleared(SqlCommand owner)
}

private CommandType _commandType;
private int _commandTimeout = ADP.DefaultCommandTimeout;
private int? _commandTimeout;
private UpdateRowSource _updatedRowSource = UpdateRowSource.Both;
private bool _designTimeInvisible;

Expand Down Expand Up @@ -572,7 +572,7 @@ override public int CommandTimeout
{
get
{
return _commandTimeout;
return _commandTimeout ?? DefaultCommandTimeout;
}
set
{
Expand All @@ -592,10 +592,18 @@ override public int CommandTimeout
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ResetCommandTimeout/*'/>
public void ResetCommandTimeout()
{
if (ADP.DefaultCommandTimeout != _commandTimeout)
if (ADP.DefaultCommandTimeout != CommandTimeout)
{
PropertyChanging();
_commandTimeout = ADP.DefaultCommandTimeout;
_commandTimeout = DefaultCommandTimeout;
}
}

private int DefaultCommandTimeout
{
get
{
return _activeConnection?.CommandTimeout ?? ADP.DefaultCommandTimeout;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,16 @@ public override int ConnectionTimeout
}
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/CommandTimeout/*' />
public int CommandTimeout
{
get
{
SqlConnectionString constr = (SqlConnectionString)ConnectionOptions;
return ((null != constr) ? constr.CommandTimeout : SqlConnectionString.DEFAULT.Command_Timeout);
}
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/AccessToken/*' />
// AccessToken: To be used for token based authentication
public string AccessToken
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ internal static partial class DEFAULT
internal const ApplicationIntent ApplicationIntent = DbConnectionStringDefaults.ApplicationIntent;
internal const string Application_Name = TdsEnums.SQL_PROVIDER_NAME;
internal const string AttachDBFilename = "";
internal const int Command_Timeout = ADP.DefaultCommandTimeout;
internal const int Connect_Timeout = ADP.DefaultConnectionTimeout;
internal const string Current_Language = "";
internal const string Data_Source = "";
Expand Down Expand Up @@ -67,6 +68,8 @@ internal static class KEY
internal const string ColumnEncryptionSetting = "column encryption setting";
internal const string EnclaveAttestationUrl = "enclave attestation url";
internal const string AttestationProtocol = "attestation protocol";

internal const string Command_Timeout = "command timeout";
internal const string Connect_Timeout = "connect timeout";
internal const string Connection_Reset = "connection reset";
internal const string Context_Connection = "context connection";
Expand Down Expand Up @@ -210,6 +213,7 @@ internal static class TRANSACTIONBINDING
private readonly string _enclaveAttestationUrl;
private readonly SqlConnectionAttestationProtocol _attestationProtocol;

private readonly int _commandTimeout;
private readonly int _connectTimeout;
private readonly int _loadBalanceTimeout;
private readonly int _maxPoolSize;
Expand Down Expand Up @@ -265,6 +269,7 @@ internal SqlConnectionString(string connectionString) : base(connectionString, G
_userInstance = ConvertValueToBoolean(KEY.User_Instance, DEFAULT.User_Instance);
_multiSubnetFailover = ConvertValueToBoolean(KEY.MultiSubnetFailover, DEFAULT.MultiSubnetFailover);

_commandTimeout = ConvertValueToInt32(KEY.Command_Timeout, DEFAULT.Command_Timeout);
_connectTimeout = ConvertValueToInt32(KEY.Connect_Timeout, DEFAULT.Connect_Timeout);
_loadBalanceTimeout = ConvertValueToInt32(KEY.Load_Balance_Timeout, DEFAULT.Load_Balance_Timeout);
_maxPoolSize = ConvertValueToInt32(KEY.Max_Pool_Size, DEFAULT.Max_Pool_Size);
Expand Down Expand Up @@ -307,6 +312,11 @@ internal SqlConnectionString(string connectionString) : base(connectionString, G
throw ADP.InvalidConnectionOptionValue(KEY.Connect_Timeout);
}

if (_commandTimeout < 0)
{
throw ADP.InvalidConnectionOptionValue(KEY.Command_Timeout);
}

if (_maxPoolSize < 1)
{
throw ADP.InvalidConnectionOptionValue(KEY.Max_Pool_Size);
Expand Down Expand Up @@ -490,6 +500,7 @@ internal SqlConnectionString(SqlConnectionString connectionOptions, string dataS
_pooling = connectionOptions._pooling;
_replication = connectionOptions._replication;
_userInstance = userInstance;
_commandTimeout = connectionOptions._commandTimeout;
_connectTimeout = connectionOptions._connectTimeout;
_loadBalanceTimeout = connectionOptions._loadBalanceTimeout;
#if netcoreapp
Expand Down Expand Up @@ -545,6 +556,7 @@ internal SqlConnectionString(SqlConnectionString connectionOptions, string dataS
internal bool Replication { get { return _replication; } }
internal bool UserInstance { get { return _userInstance; } }

internal int CommandTimeout { get { return _commandTimeout; } }
internal int ConnectTimeout { get { return _connectTimeout; } }
internal int LoadBalanceTimeout { get { return _loadBalanceTimeout; } }
internal int MaxPoolSize { get { return _maxPoolSize; } }
Expand Down Expand Up @@ -633,6 +645,7 @@ internal static Dictionary<string, string> GetParseSynonyms()
#if netcoreapp
{ KEY.PoolBlockingPeriod, KEY.PoolBlockingPeriod},
#endif
{ KEY.Command_Timeout, KEY.Command_Timeout },
{ KEY.Connect_Timeout, KEY.Connect_Timeout },
{ KEY.Connection_Reset, KEY.Connection_Reset },
{ KEY.Context_Connection, KEY.Context_Connection },
Expand Down
Loading