I have created this stored procedure in SQL Server 2008 R2:
CREATE PROCEDURE dbo.test AS
BEGIN
WAITFOR DEALY '00:00:40'
END
I have also written a C# console app to test the connect timeout property.
static void Main(string[] args)
{
OpenSqlConnection();
Console.ReadLine();
}
private static void OpenSqlConnection()
{
string connectionString = GetConnectionString();
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand("dbo.test", connection) { CommandType = CommandType.StoredProcedure })
{
connection.Open();
Console.WriteLine("ConnectionTimeout: {0}", connection.ConnectionTimeout);
command.ExecuteNonQuery();
Console.WriteLine("Finished");
connection.Close();
}
}
}
static private string GetConnectionString()
{
return
"Data Source=test.com;Initial Catalog=test_db;Integrated Security=True;MultipleActiveResultSets=True;Connect Timeout=10; Application Name=Test";
}
There was a connection timeout exception returned as excepted (timeout in connection string < 40s). However, when I changed the Connect Timeout property to 120, I still got the same timeout exception. After some trial and error, it seems that the timeout value is always 30s regardless of my connection string value.
Is the connection timeout controlled by somewhere else? (if yes, where?)
Why the connect timeout value in connection string has no effect on my console app?
Update
Thanks all. I have just noticed that the command timeout is different from connection timeout(timeout in connection string).
Instead of changing my app.config, I would have to specify the CommandTimeout property as Sudipta Maiti suggested and recompile my code.
There is a similar issue in:
http://forums.asp.net/t/1197160.aspx?Can+you+change+command+timeout+via+the+connection+string+
Use CommandTimeout:
using (var command = new SqlCommand("dbo.test", connection) {
CommandType = CommandType.StoredProcedure })
{
connection.Open();
Console.WriteLine("ConnectionTimeout: {0}",
connection.ConnectionTimeout);
command.CommandTimeout = 120;
command.ExecuteNonQuery();
Console.WriteLine("Finished");
connection.Close();
}
I strongly suspect the given Timeout, it may not be enough to complete your operations. So make it Connection Timeout=30;
Connect Timeout -or- Connection Timeout by default the value will be 15 seconds. Based on your operation performance you might need to extend the seconds.
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.
A value of zero (0) causes pooled connections to have the maximum connection timeout.
There is a Sample Source almost same as yours.
Related
I'm doing some experimentation with ADO.Net and EF in order to better understand how it handles the SQL Server connections.
I found something very interesting with ADO.Net. I am creating multiple tasks that calls a simple insert SQL script with the proper wait to dispose SqlConnection and SqlCommand. Nothing special here, but when the 10k tasks finishes processing, all the SQL connections are still hanging (I confirmed by running sp_who). The only way those connections get cleared up is when the application instance is closed.
How is that even possible? I tried many things to force it to close, = null the the data access instance + forced GC but nothing...
I'm trying to make sense from this behavior but I am failing. Any clues?
static void Main(string[] args)
{
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss"));
for (int i = 0; i < 10000; i++)
{
Task.Run(() =>
{
var dbLegacy = new DataAccessLegacy();
dbLegacy.TableBInsert();
dbLegacy = null;
});
}
Console.ReadKey();
}
public void TableBInsert()
{
using (SqlConnection connection = new SqlConnection(#"Password=qpqp;Persist Security Info=True;User ID=sqlUser2;Initial Catalog=DatabaseA;Data Source=VM2HOSTNAME\VM2INSTANCEA"))
{
using (SqlCommand command = new SqlCommand("DatabaseBInsert", connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("ColAInt", SqlDbType.Int);
command.Parameters[0].Value = (new Random()).Next(0, 5000);
command.Parameters.Add("ColBTinyInt", SqlDbType.TinyInt);
command.Parameters[1].Value = (new Random()).Next(1, 255);
command.Parameters.Add("ColCVarchar", SqlDbType.VarChar);
command.Parameters[2].Value = Convert.ToChar((new Random()).Next(1, 255)).ToString();
command.Parameters.Add("ColDVarcharMax", SqlDbType.VarChar);
command.Parameters[3].Value = Convert.ToChar((new Random()).Next(1, 255)).ToString();
command.Parameters.Add("ColEDecimal", SqlDbType.Decimal);
command.Parameters[4].Value = (new Random()).Next(0, 5000) + 0.5;
command.Parameters.Add("ColFSmallInt", SqlDbType.SmallInt);
command.Parameters[5].Value = (new Random()).Next(0, 5000);
command.Parameters.Add("ColGDateTime", SqlDbType.DateTime);
command.Parameters[6].Value = DateTime.Now;
command.Parameters.Add("ColHChar", SqlDbType.Char);
command.Parameters[7].Value = Convert.ToChar((new Random()).Next(1, 255)).ToString();
command.Parameters.Add("ColINVarchar", SqlDbType.NVarChar);
command.Parameters[8].Value = Convert.ToChar((new Random()).Next(1, 255)).ToString();
command.Parameters.Add("ColJNChar", SqlDbType.NChar);
command.Parameters[9].Value = Convert.ToChar((new Random()).Next(1, 255)).ToString();
connection.Open();
command.ExecuteScalar();
connection.Close();
command.Dispose();
}
connection.Dispose();
}
}
By default, ADO.Net uses connection pooling. From the docs (emphasis mine):
Connection pooling reduces the number of times that new connections must be opened. The pooler maintains ownership of the physical connection. It manages connections by keeping alive a set of active connections for each given connection configuration. Whenever a user calls Open on a connection, the pooler looks for an available connection in the pool. If a pooled connection is available, it returns it to the caller instead of opening a new connection. When the application calls Close on the connection, the pooler returns it to the pooled set of active connections instead of closing it. Once the connection is returned to the pool, it is ready to be reused on the next Open call.
In connectivity of SQL database using ADO.Net C#, I am getting exceptions randomly while working with thousands of data simultaneously which is being executed in thread such as
A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 0 - The wait operation timed out.)
The client was unable to establish a connection because of an error during connection initialization process before login. Possible causes include the following: the client tried to connect to an unsupported version of SQL Server; the server was too busy to accept new connections; or there was a resource limitation (insufficient memory or maximum allowed connections) on the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)
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.
My connection string is as
<add name="ConnDBString" connectionString="datasource;Initial Catalog=dbname;pooling=true;connection lifetime=120;Max Pool Size=1000" providerName="System.Data.SqlClient"/>
In reference of other questions I have optimized my code for connection establishment like below
public static int ExecuteNonQuery(string commandText, CommandType commandType, ref List<SqlParameter> parameters)
{
int result = 0;
if (!string.IsNullOrEmpty(commandText))
{
using (var cnn = new SqlConnection(Settings.GetConnectionString()))
{
var cmd = cnn.CreateCommand();
cmd.CommandText = commandText;
cmd.CommandType = commandType;
cmd.CommandTimeout = Convert.ToInt32(Settings.GetAppSetting("CommandTimeout") ?? "3600");
cmd.Parameters.AddRange(parameters.ToArray());
cnn.Open();
result = cmd.ExecuteNonQuery();
cmd.Dispose();
}
}
return result;
}
Please advise.
Please make sure whether your ram is reaching max limit as #mjwills say .
and i have write something . you can try this which might help you for max pool size issue .
public static int ExecuteNonQuery(string commandText, CommandType commandType, ref List<SqlParameter> parameters)
{
int result = 0;
if (!string.IsNullOrEmpty(commandText))
{
using (var cnn = new SqlConnection(Settings.GetConnectionString()))
using (var cmd = cnn.CreateCommand())
{
cmd.CommandText = commandText;
cmd.CommandType = commandType;
cmd.CommandTimeout = Convert.ToInt32(Settings.GetAppSetting("CommandTimeout") ?? "3600");
cmd.Parameters.AddRange(parameters.ToArray());
cnn.Open();
result = cmd.ExecuteNonQuery();
cnn.Close();
}
}
return result;
}
you can also make this method sync for utilise your memory .
I'm creating database, using ADO.NET. Basically, I'm executing SQL commands in next way:
private bool ExecuteSqlCommand(string command)
{
var success = true;
using (var connection = GetSqlConnection())
{
if (connection == null)
return false;
using (var myCommand = new SqlCommand("query", connection))
{
try
{
connection.Open();
myCommand.CommandText = command;
myCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
success = false;
Log.LogMessage(string.Format("Unable to execute SQL command: {0}", ex.Message));
}
}
}
return success;
}
GetSqlConnection just gets some proper SqlConnection with connection string like
"Server={0}\\{1};User Id={2};Password={3};Application Name={4};"
It works well, and executes command properly, with one exception - according to Sql Manager Studio activity monitor, it remains as active connection even after method was executed.
According to question Why does my SqlConnection remain in the SSMS Processes list after closing it?, this is correct behavior, since connection might be reused. But the serius issue is, that later, READ_COMMITTED_SNAPSHOT command will be called for this database, while using different SqlConnection. Which leads to exception, since READ_COMMITTED_SNAPSHOT requires, that connection, which is used to call this command, should be the only connection to database.
I can't reuse this connection for further operations with database, since I use different connection string for them, with database specified as InitialCatalog (obviously, I can't use it, while database doesn't exist).
So, can I somehow remove this initial connection?
Execute SqlConnection.ClearPool This will mark all connections to be discarded instead of recycled.
[Disclaimer] : I think I have read every stackoverflow post about this already
I have been breaking my head over this for quite some time now. I am getting the following exception in my asp.net web.api.
Exception thrown: 'System.InvalidOperationException' in mscorlib.dll
Additional information: 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.
Most people suggested that I should look for leaked connections in my application. Here is my code. Now I am sure that I am not leaking any connections
public async Task<IEnumerable<string>> Get()
{
var ds = new DataSet();
var constring = "Data Source=xxx;Initial Catalog=xxx;User Id=xxx;Password=xxx;Max Pool Size=100";
var asyncConnectionString = new SqlConnectionStringBuilder(constring)
{
AsynchronousProcessing = true
}.ToString();
using (var con = new SqlConnection(asyncConnectionString))
using (var cmd = new SqlCommand("[dbo].[xxx]", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#x1", 1);
cmd.Parameters.AddWithValue("#x2", "something");
await con.OpenAsync();
using (var rdr =await cmd.ExecuteReaderAsync())
{
if (rdr.HasRows)
{
ds.Load(rdr, LoadOption.OverwriteChanges, "MyTable");
}
rdr.Close();
con.Close();
ds.Dispose();
}
}
//I know this looks wrong, just an empty api method to show the code
return new string[] { "value1", "value2" };
}
The exception does not occur when I am using my local Sql Server. Only happens when I connect to our 'test server'. Are there anything else I can look at when trying resolve this issue. Like Sql server settings / network settings etc.
The stored procedure I call does not lock up the db I have checked for that as well. If that was the case it should have failed on my local Sql instance as well.
I am using jmeter to generate load, 1500 - threads(users). Surely I should be able to handle way more than that.
Thanks in advance
You have not specified any Connection Time out property, so it's 15 seconds default. using Max Pool Size=100 is not a good idea until you don't have proper hardware resources.
You started 1500 threads, so it seems that the some the threads keep waiting for 15 seconds to get their chance for connection opening. And as time goes out, you get the connection time out error.
So I think increasing the 'Connection Timeout' property in connection string may resolve your issue.
I want to set the querytimeout from the connection string.
not the connection timeout, is it possible?
No. It's per command, not per connection.
Edit, May 2013
As requested in comment:
SQLCommand.CommandTimeout for command execution
There is no matching SQLConnection property (the questions says not the SqlConnection.ConnectionTimeout property
Some more notes about commands and execution time outs in SQL Server (DBA.SE).
And more SO stuff: What happens to an uncommitted transaction when the connection is closed?
You have always been able to specify the Connect Timeout via the SqlClient connection string, this applies to establishing a connection with the database server, not executing commands / running queries.
The default Connect Timeout is 15 seconds.
With the release of Microsoft.Data.SqlClient v2.1 it's introduced the "Command Timeout" connection string property to override, if required, the default of 30 seconds for this property.
Hence it is now possible to set the default command timeout via the connection string.
In order to use this new feature, with EF Core 3 and 5, you must add an explicit dependency on the updated SqlClient package by adding the following to your project file:
<PackageReference Include="Microsoft.Data.SqlClient" Version="2.1.0" />
In addition, you must update your connection string in order to increase the default command timeout - keep in mind that this will apply to your entire application, unless overridden in code by setting the SqlCommand.CommandTimeout property.
Connection string examples:
"YourDatabaseAlias": "Server={serverURL}; Initial Catalog={db}; Integrated Security=true; Command Timeout=60"
The connection string above sets the command timeout to 1 minute (60 seconds).
Hope this is useful.
See:- ConnectionStrings content on this subject. There is no default command timeout property.
You can only set the connection timeout on the connection string, the timeout for your query would normally be on the command timeout.
(Assuming we are talking .net here, I can't really tell from your question).
However the command timeout has no effect when the command is executed against a context connection (a SqlConnection opened with "context connection=true" in the connection string).
I have tried different values for the parameter Command Timeout in the below connection string and it worked every time as expected.
Data Source=Your_Db_Server;Initial Catalog=Your_DB;Integrated Security=true;TrustServerCertificate=true;Connect Timeout=600;Command Timeout=120
Only from code:
namespace xxx.DsXxxTableAdapters {
partial class ZzzTableAdapter
{
public void SetTimeout(int timeout)
{
if (this.Adapter.DeleteCommand != null) { this.Adapter.DeleteCommand.CommandTimeout = timeout; }
if (this.Adapter.InsertCommand != null) { this.Adapter.InsertCommand.CommandTimeout = timeout; }
if (this.Adapter.UpdateCommand != null) { this.Adapter.UpdateCommand.CommandTimeout = timeout; }
if (this._commandCollection == null) { this.InitCommandCollection(); }
if (this._commandCollection != null)
{
foreach (System.Data.SqlClient.SqlCommand item in this._commandCollection)
{
if (item != null)
{ item.CommandTimeout = timeout; }
}
}
}
}
//....
}
I find answer in FollowCode:
SqlDataAdapter da = new SqlDataAdapter(Query, ConnectionString);
da.SelectCommand.CommandTimeout = queryTimeoutInSeconds;
you can set Timeout in connection string (time for Establish connection between client and sql). commandTimeout is set per command but its default time is 30 secend