I have a ASP.net application in which I do a query on a SQL Server Database. When the query ends, I do the following :
reader.Close();
reader.Dispose();
conn.Close();
conn.Dispose();
And still when I go on SQL Server and does :
SELECT
DB_NAME(dbid) as DBName,
COUNT(dbid) as NoOfConnections,
loginame as LoginName
FROM
sys.sysprocesses
WHERE
dbid > 0
GROUP BY
dbid, loginame
I can see the 'NoOfConnections' that keeps increasing while I have closed the connection and there is a moment where I'll get an error because I have over 100 connections opened. How do I close the connections properly?
SQL Server connection pooling will cache connections. You can clear all connection pools with this:
conn.ClearAllPools();
For more info, see here.
To clear the connection pool for a specific connection, you can use the ClearPool method. For example:
conn.ClearPool();
For more info, see here.
You can configure the size of the connection pool through the connection string, for example:
Provider=SQLOLEDB;Data Source=ServerName;Integrated Security=SSPI;Min Pool Size=5; Max Pool Size=20;
You can turn off pooling in the connection string also, for example:
Provider=SQLOLEDB;Data Source=ServerName;Integrated Security=SSPI;Pooling=false;
Connection Pooling is on by default, the default size of the connection pool is 100. If the client connection string is the same, the pool will try and use a connection from the connection pool - if it is available. For more see here.
Instead of doing this
reader.Close();
reader.Dispose();
conn.Close();
conn.Dispose();
Why not use using statements? Example, for Connection:
using (var conn = new SqlConnection("YourConnectionString"))
{
//your code here
}
This will close and dispose of the SqlConnection object for you.
Related
I'm using multiple connections in different methods, but when I close the connection, the connection sessions hangs in database sessions as inactive until I terminate the .exe file. I'm using connections in using statement like:
using(OracleConnection con = new OracleConnection(constring))
{
con.Open();
}
And I also tried to close and dispose the connection manually and use OracleConnection.ClearPool(con) and OracleConnection.ClearAllPools() but none of them works.
the reference im using:
System.Data.OracleClient version 2.0.0.0
connection string
Data Source = ip/db; User Id = user; Password=pw;
This behaviour is normal because if you Dispose(); a connection the ConnectionPool from Oracle doesn't really destroy the connection but set the status to 'free'. So the next time you open a connection, you don't really open a new connection, you just look for a 'free' connection in your ConnectionPool and use this one. If no free Connection exists, a new one will be created.
This behaviour garants you a better performance because Open/Close Connections cost much afford.
If you use:
using(OracleConnection con = new OracleConnection(constring))
{
}
or
con.Close();
This is the same as you use Dispose();. Using just make sure that the Dispose is called on the end of your using block. That's why using only works on objects which implement IDisposable.
So far ok...But why doesn't OracleConnection.ClearAllPools()close the connections? It does but Oracle directly create a new Connection, so that your ConnectionPool is filled up to your MinPool-Size. This is the reason why BigTallJosh's code:
"Min Pool Size = 0; Max Pool Size = 16; Incr Pool Size = 2; Decr Pool
Size = 1; Validate Connection = False; Connection Lifetime = 0;
stop this behaviour. A Min Pool Size of 0 will stop automatic creation of new connections.
Here you can find a good explanation about ClearAllPools(); Method.
So to finally answer your question. Set the MinPoolSize=0 and after that call connection.ClearAllPools();. This should work.
I'm making a C#program that interacts with some SQL Server databases. The problem is if I connect to a database (dbA) and then close this connection and open another one to another database (dbB) and then do a Restore of dbA, the SqlException triggers saying that database (dbA) is in use. However if I execute the program and connect only to dbB, I can restore the other databases without problem, is like the first connection is kept stored. Anyway here is the code where the connection should open and close:
private bool CheckConnection()
{
bool res = false;
string conString = string.Empty;
if (!String.IsNullOrEmpty(serverBox.Text) && !String.IsNullOrEmpty(dbBox.Text))
{
conString = ConcatConString(dbBox.Text);
using (SqlConnection conn = new SqlConnection(conString))
{
conn.Open();
if (conn.State == ConnectionState.Open)
{
res = true;
}
}
}
return res;
}
ADO.NET uses connection pooling to reuse expensive connection objects. When you close a connection, any existing transactions are rolled back, its server-side state is reset and it's placed in the connection pool awating for the next Open command.
To the server though, that still counts as a server connection when you try to take such drastic actions as shutting down the server, restoring the database etc. That means that you have to take explicit action and tell the server that it's OK to proceed.
In this case, you need to set the database to SINGLE USER mode, perform the restore operation then bring it back to MULTI USER mode, eg:
ALTER DATABASE [MyDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
RESTORE DATABASE [MyDB] ...
ALTER DATABASE [MyDB] SET MULTI_USER
That's what SSMS does by the way, when you check the "Close Existing Connections to Database" option when restoring
You can also use WITH ROLLBACK AFTER xx SECONDS if you want give some time to existing connections to finish. In this case though, you are going to overwrite the database.
Closing a connection does not close it at the database, it just returns the connection to the pool maintained by ADO.Net. Normally I would never suggest this but it seems you may have a legitimate case for disabling connection pooling.
In the connection string set the Pooling attribute to no or false and the connection should actually close on the server.
You can observe how it works by running sp_who2 in SSMS with connection pooling enabled or disabled in the following code:
class Program
{
static void Main(string[] args)
{
SqlConnectionStringBuilder bldr = new SqlConnectionStringBuilder();
bldr.IntegratedSecurity = true;
bldr.InitialCatalog = "YourDB";
bldr.DataSource = "(localdb)\\YourServer";
bldr.Pooling = false; //Comment and uncomment this and run sp_who2
using (SqlConnection con = new SqlConnection(bldr.ConnectionString))
{
con.Open();
}
}
}
Update
Don't do this unless your program is the only thing connecting. I got the impression that the program was specifically for restoring databases. If you have other clients on the databases then this will tank performance.
I am trying to design an efficient application that connects to a SQL Database and I was wondering what the merits/demerits of creating a SQL connection for each SQL query is,
Eg, Like the code below, making a class with the connection set once so you can call on it when ever you need it in the class.
class SqlQuery
{
SqlConnection Connection = new SqlConnection(#myConnectionString);
public void fillInfoData()
{
SqlCommand updateCommand = new SqlCommand(
#"my sql query", Connection);
Connection.Open();
updateCommand.ExecuteNonQuery();
Connection.Close();
}
}
Or should you create a new connection for each new query?
EDIT: Jon Skeet recommended creating a new connection for each query,
I was wondering why?
EDIT No 2: He stated it in this answer.
You open a connection per query and then when you close it, it goes back to the connection pool and the framework will manage the rest
So you do not have to worry about keeping connection alive, timeouts etc...
MSDN Article
https://msdn.microsoft.com/en-us/library/8xx3tyca(v=vs.110).aspx
I think what he meant was not to keep a global connection object that is open. But you need to create an SqlConnection when you need it, execute all the queries needed at the point (Not a single connection per each query) and then close the connection.
So if you have a bunch of queries that needs to be executed, you don't need a single sql connection for each but one is only enough. But if you're executing a query each time the user clicks a button for example, it's better to open a connection on each click, because that way it is easier to manage closing and disposing the connection.
I'm writing an application in ASP.NET, where I do frequent SQL Connections and by frequent I mean every 2 seconds. It's real time data application.
BD Engine is SQL SERVER 2008R2.
Each user connects to at least two different databases.
My problem is I still cant understand the connection pooling and how much of them connections I'll have after some queries.
I implemented the following methods:
private static string composeConnectionString(string connectTo)
{
StringBuilder sqlSB = new StringBuilder("Data Source=");
sqlSB.Append(dataSource);
sqlSB.Append(";Min Pool Size=");
sqlSB.Append(minPoolSize);
sqlSB.Append(";Max Pool Size=");
sqlSB.Append(maxPoolSize);
sqlSB.Append(";Connection Timeout=");
sqlSB.Append(connectionTimeout);
sqlSB.Append(";Initial Catalog=");
sqlSB.Append(connectTo);
sqlSB.Append(";Integrated Security=");
sqlSB.Append(integratesSecurity);
sqlSB.Append(";User Id=");
sqlSB.Append(userId);
sqlSB.Append(";Password=");
sqlSB.Append(password);
sqlSB.Append(";MultipleActiveResultSets=");
sqlSB.Append(multipleActiveResultSets);
return sqlSB.ToString();
}
public static SqlConnection getConnection(string connectTo)
{
SqlConnection connection = null;
string connectionString = composeConnectionString(connectTo);
try
{
connection = new SqlConnection(connectionString);
}
catch (Exception ex)
{
if (connection != null)
connection = null;
ExceptionLogger.LogException(ex, connectionString);
}
return connection;
}
At this point, I begin to question if new ConnectionPool is creater for every SQLConnection I seek?
How secure is the connection string?
Ask me for updates if something seem blurry.
Thank you all.
Depends of your configuration. If you configure your pool for at least one connection and a maximum of 3, when your first connection happens, if pooling is enabled, the connection will check for at least 1 and maximum of 3.
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.
You can read more here: https://msdn.microsoft.com/en-us/library/8xx3tyca%28v=vs.110%29.aspx
About the connection string, if you use user name and password as credentials, you have a security issue. You can use Windows Authentication to ensure your connection string does not have any sensitive data, or, if you're using IIS, you can store the connection string on it to protect your data.
Read more about connection string here: https://msdn.microsoft.com/pt-br/library/system.data.sqlclient.sqlconnection.connectionstring%28v=vs.110%29.aspx
And about protecting the connection string here: https://msdn.microsoft.com/en-us/library/89211k9b%28v=vs.110%29.aspx
Hope it helps.
When I run this code, the number of connections to my DB increases to 3 after connection.Open(). Why does it not go back down to 2 after connection.Close()?
private static void AdoNetStuff()
{
var connection = new SqlConnection(#"Initial Catalog=abook;server=.\SqlExpress;Integrated Security=true");
var sqlCommand = new SqlCommand("SELECT TOP 10 * FROM dbo.Entity", connection);
connection.Open();
sqlCommand.ExecuteReader();
sqlCommand.Dispose();
connection.Dispose();
connection.Close();
}
The above code is in a console app, and the number of connections doesn't drop back down to 2 until my console app closes.
This is how I'm checking the number of connections.
SELECT DB_NAME(dbid) as DBName, COUNT(dbid) as NumberOfConnections, loginame as LoginName
FROM sys.sysprocesses
WHERE dbid > 0 AND DB_NAME(dbid) = 'abook'
GROUP BY dbid, loginame
I can wait a while before ending the console app, and I still have 3 connections. As soon as I end the app, the number of connections drop back down to 2.
SQL server uses connection pools for performance reasons. That means your connections will stay active even through you have called dispose.
Try calling:
SQLConnection.ClearAllPools();
To clear just the current connection try calling:
SqlConnection.ClearPool(ObjSqlConnection);
It appears that you are disposing before closing - .Dispose should be the last thing you do to a disposable object before you set the object variable to Nothing.
By disposing of a command and/or connection before closing it, you could be leaving the connection open.
Perhaps you could use a Using block for your connection and sqlCommand.