C# WinForm Oracle sessions hangs after connection closed - c#

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.

Related

C# - SQL Connection won't close

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.

EF DBContext dispose not closing the connection

I am using the EF 6.1.0
I have below custom DBContex object as DBEntites
public partial class DbEntities : DbContext
{
public DbEntities()
: base("name=DbEntities")
{
////Configuration.LazyLoadingEnabled = true;
////Configuration.ProxyCreationEnabled = false;
}
//// I have ALL Entites added as below
////public virtual IDbSet<CCode> CCodes { get; set; }
}
I have the below operations on context object
using (var context = new DbEntities())
{
var entitySet = context.Set<T>();
var res = entitySet.Where<T>(predicate).ToList();
if (context.Database.Connection.State == ConnectionState.Open)
{
context.Database.Connection.Close();
}
return res;
}
But after disposing the context object still i can see a active DB Connection. On connection state condition i can see that the connection is already closed(the connection had never true).
I am using the below query to see the connection on SQL.
select db_name(dbid) , count(*) 'connections count'
from master..sysprocesses
where spid > 50 and spid != ##spid
group by db_name(dbid)
order by count(*) desc
At the below statement a sql connection count increased. But it was never down even after disposing . (I mean after using block excuted it supposed to close the connection).
var res = entitySet.Where<T>(predicate).ToList();
Any help would be greatly appreciated.
As was figured out in comments, the reason is indeed connection pooling performed by .NET. .NET maintains a pool of connections for every connection string you use in your application, for perfomance reasons (because opening and closing connections often might be costly in terms of perfomance). That pool has certain minimum and maximum size (controlled by MinPoolSize and MaxPoolSize connection string parameters). When you open a connection (via SqlConnection.Open) - it might be taken out of the pool and not really opened afresh. When you close connection (which is also done by disposing EF context) - connection might be put into the pool instead, and not really closed. When connection is idle for certain time (about 5 minutes) - it might be removed from the pool.
If you (for some reason) want to avoid that, you can either set MaxPoolSize to 0 for your connection string, or clear pool explicitly by SqlConnection.ClearPool or SqlConnection.ClearAllPools.
Just to register my experience here. I had same problem with EF Core 6 + Postgres and the solution was just to disable "Pooling" in the connection string.
Pooling=false;

Understanding ASP.NET ConnectionPool and string security

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.

Start and close SQL connection - At start and in the end or every time needed?

I'm making a web application in C# with ASP.Net, and I'm using an SQL database for it. In the guides I saw (about SqlConnection and SqlCommand) they open and close the SQL connection each time they want to send a query. But I'm not sure this is the best way to handle the connection, because I also learned some PHP, and as far as I know in PHP you open a connection only once, at start. So what is the best way to handle the connection?
You should generally have one connection, and transaction, for the length of the web request.
If you have two connections, you could potentially have inconsistent data. e.g. in the first query you check the bank balance, then you close it. You then add $5 to the balance and save that away in the next connection. What if someone else added $5 between the two connections? It would go missing.
The easiest thing to do is to open the connection global.asax BeginRequest and save that away into the HttpContext. Whenever you need a connection, pull it from there. Make sure that you .Close the connection in your EndRequest
Also, read up here on connection pooling: http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx
It is not 'expensive' to repeatedly open and close connections, provided the username is the same each time.
Ado.Net has connection pooling already managed for you, so you don't need to worry about reusing connections.
You could use the Using statement to close and dispose connection:
DataTable dt = new DataTable();
using (SqlConnection conn = new SqlConnection("my_connection_string"))
{
using (SqlDataAdapter adapter = new SqlDataAdapter("SELECT * from Table", conn))
{
conn.open();
adapter.Fill(dt);
}
}
Normal practice in .NET is to open a SqlConnection and use a SqlCommand, then dispose of both of them.
using(SqlConnection connection = new SqlConnection("myConnectionString"))
{
using(SqlCommand command = new SqlCommand("dbo.SomeProc"))
{
// Execute the command, when the code leaves the using block, each is disposed
}
}
As a connection to database is an expensive resource it's better to open sql connection as late as possible and close early. So you should open the connection just before executing a command and close it once you have executed it.
On the other hand if you are going to execute many commands in a short interval of time it's better to open the connection once and close after all the commands are executed.
For starters they do not as there is a connection pool that is being used, but SqlCommand has an overload to take a connection object, so you could keep the connection around and pass it.
Generally:
using (var ts = new TransactionScope())
{
using (var connection = new SqlConnection(...))
{
using (var command = new SqlCommand(connection, ...)
{
...
}
using (var command = new SqlCommand(connection, ...)
{
...
}
}
ts.Complete();
}
Of course I would recommend using LINQ-to-SQL or EF at this point.
Try Data Access Application Block in the Enterprise Library if you do not want to worry about opening and closing the connections.

Access to SQL DB in multithread server app

In my server application I want to use DB (SQL Server) but I am quite unsure of the best method. There are clients whose requests comes to threadpool and so their processing is async. Every request usually needs to read or write to DB, so I was thinking about static method which would create connection, execute the query and return the result. I'm only afraid whether opening and closing connection is not too slow and whether some connection limit could not be reached? Is this good approach?
IMHO the best is to rely on the ADO.NET connection pooling mechanism and don't try to handle database connections manually. Write your data access methods like this:
public void SomeMethod()
{
using (var connection = new SqlConnection(connectionString))
using (var command = connection.CreateCommand())
{
connection.Open();
command.CommandText = "SELECT Field1 FROM Table1";
using (var reader = command.ExecuteReader())
{
while(reader.Read())
{
// do something with the results
}
}
}
}
Then you can call this method from wherever you like, make it static, call it from threads whatever. Remember that calling Dispose on the connection won't actually close it. It will return it to the connection pool so that it can be reused.
Surprised that no one mentioned connection pooling. If you think you are going to have a large number of requests, why not just setup a pool with a min pool size set to say 25 (arbitrary number here, do not shoot) and max pool size set to say 200.
This will decrease the number of connection attempts and make sure that if you are not leaking connection handles (something that you should take explicit care to not let happen), you will always have a connection waiting for you.
Reference article on connection pooling: http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx
Another side note, why the need to have the connection string in the code? Set it in the web.config or app.config for the sake of maintainability. I had to "fix" code that did such things and I always swore copiously at the programmer responsible for such things.
I have had exactly the same problem like you. Had huge app that i started making multithreaded. Benefit over having one connection open and being reused is that you can ask DB multiple times for data as new connection is spawned on request (no need to wait for other threads to finish getting data), and if for example you loose connection to sql (and it can happen when network goes down for a second or two) you will have to always check if connection is open before submitting query anyway.
This is my code for getting Database rows in MS SQL but other stuff should be done exactly the same way. Keep in mind that the sqlConnectOneTime(string varSqlConnectionDetails) has a flaw of returning null when there's no connection so it needs some modifications for your needs or the query will fail if sql fails to establish connection. You just need to add proper code handling there :-) Hope it will be useful for you :-)
public const string sqlDataConnectionDetails = "Data Source=SQLSERVER\\SQLEXPRESS;Initial Cata....";
public static string sqlGetDatabaseRows(string varDefinedConnection) {
string varRows = "";
const string preparedCommand = #"
SELECT SUM(row_count) AS 'Rows'
FROM sys.dm_db_partition_stats
WHERE index_id IN (0,1)
AND OBJECTPROPERTY([object_id], 'IsMsShipped') = 0;";
using (var varConnection = Locale.sqlConnectOneTime(varDefinedConnection))
using (var sqlQuery = new SqlCommand(preparedCommand, varConnection))
using (var sqlQueryResult = sqlQuery.ExecuteReader())
while (sqlQueryResult.Read()) {
varRows = sqlQueryResult["Rows"].ToString();
}
return varRows;
}
public static SqlConnection sqlConnectOneTime(string varSqlConnectionDetails) {
SqlConnection sqlConnection = new SqlConnection(varSqlConnectionDetails);
try {
sqlConnection.Open();
} catch (Exception e) {
MessageBox.Show("Błąd połączenia z serwerem SQL." + Environment.NewLine + Environment.NewLine + "Błąd: " + Environment.NewLine + e, "Błąd połączenia");
}
if (sqlConnection.State == ConnectionState.Open) {
return sqlConnection;
}
return null;
}
Summary:
Defined one global variable with ConnectionDetails of your SQL Server
One global method to make connection (you need to handle the null in there)
Usage of using to dispose connection, sql query and everything when the method of reading/writing/updating is done.
The one thing that you haven't told us, that would be useful for giving you an answer that's appropriate for you is what level of load you're expecting your server application to be under.
For pretty much any answer to the above question though, the answer would be that you shouldn't worry about it. ADO.net/Sql Server provides connection pooling which removes some of the overhead of creating connections from each "var c = new SqlConnection(connectionString)" call.

Categories