I need a to get a bit of understanding in this, When you open a connection to a Database can you leave it open?
How does this connection close?
Is it good practise or bad practice?
Currently I have a request to a database that works no problem
oCON.Open();
oCMD.ExecuteNonQuery();
oCON.Close();
However Some of the examples that I have seen are something like this with no database close.
oCON.Open();
oCMD.ExecuteNonQuery();
How would this connection get closed?
Is this bad practice?
I was looking for a duplicate, as this seems to be a common question. The top answer I found is this one, however, I don't like the answer that was given.
You should always close your connection as soon as you're done with it. The database has a finite number of connections that it allows, and it also takes a lot of resources.
The "old school" way to ensure the close occurred was with a try/catch/finally block:
SqlConnection connection;
SqlCommand command;
try
{
// Properly fill in all constructor variables.
connection = new SqlConnection();
command = new SqlCommand();
connection.Open();
command.ExecuteNonQuery();
// Parse the results
}
catch (Exception ex)
{
// Do whatever you need with exception
}
finally
{
if (connection != null)
{
connection.Dispose();
}
if (command != null)
{
command.Dispose();
}
}
However, the using statement is the preferred way as it will automatically Dispose of the object.
try
{
using (var connection = new SqlConnection())
using (var command = new SqlCommand())
{
connection.Open();
command.ExecuteNonQuery();
// Do whatever else you need to.
}
}
catch (Exception ex)
{
// Handle any exception.
}
The using statement is special in that even if an exception gets thrown, it still disposes of the objects that get created before the execution of the code stops. It makes your code more concise and easier to read.
As mentioned by christophano in the comments, when your code gets compiled down to IL, it actually gets written as a try/finally block, replicating what is done in the above example.
You want your SqlConnection to be in a using block:
using(var connection = new SqlConnection(connectionString))
{
...
}
That ensures that the SqlConnectionwill be disposed, which also closes it.
From your perspective the connection is closed. Behind the scenes the connection may or may not actually be closed. It takes time and resources to establish a SQL connection, so behind the scenes those connections aren't immediately closed. They're kept open and idle for a while so that they can be reused. It's called connection pooling. So when you open a connection, you might not really be opening a new connection. You might be retrieving one from the connection pool. And when you close it, it doesn't immediately close, it goes back to the pool.
That's all handled behind the scenes and it doesn't change what we explicitly do with our connections. We always "close" them as quickly as possible, and then the .NET Framework determines when they actually get closed. (It's possible to have some control over that behavior but it's rarely necessary.)
Take a look at the Repository Pattern with Unit of Work.
A connection context should be injected into the class which operates commands to the database.
A sql execution class - like a repository class represents - should not create a connection. It is not testable and hurts the paradigm of SRP.
It should accept an IDbConnection object like in the constructor. The repository should not take care if behind the IDbConnection is an instance of SqlConnection, MysqlConnection or OracleConnection.
All of the ADO.NET connection objects are compatible to IDbConnection.
Related
I'm working on an ASP.NET application where, as part of some logic, I want to lock some tables and do work on them. The method runs in a separate thread running as a kind of background task, spawned via a Task. The problem comes in with the error handling...
The code looks more or less like this:
MySqlConnection connection = new MySqlConnection(ConfigurationManager.AppSettings["prDatabase"]);
try
{
connection.Open();
MySqlCommand lock_tables = new MySqlCommand(Queries.lockTables(), connection);
lock_tables.ExecuteNonQuery();
// do a bunch of work here
MySqlCommand unlock_tables = new MySqlCommand(Queries.unlockTables(), connection);
unlock_tables.ExecuteNonQuery();
}
catch (MySqlException mex)
{
// Mostly error logging here
}
finally
{
connection.Close();
}
Pretty simple stuff. Everything works fine and dandy assuming nothing goes wrong. That's a terrible assumption to make, though, so I deliberately set up a situation where things would foul up in the middle and move to the finally block.
The result was that my table locks remained until I closed the app, which I learned by trying to access the tables with a different client once the method completed. Needless to say this isn't my intention, especially since there's another app that's supposed to access those tables once I'm done with them.
I could quickly fix the problem by explicitly releasing the locks before closing the connection, but I'm still left curious about some things. Everything I've read before has sworn that closing a connection should implicitly release the table locks. Obviously in this case it isn't. Why is that? Does connection.Close() not actually completely close the connection? Is there a better way I should be closing my connections?
Try wrapping your Connection and MySqlCommand instance in a using statement. That will release the objects as soon as it leaves the brackets.
using(MySqlConnection conn = new MySqlConnection(connStr))
{
conn.Open();
using(MySqlCommand command = new MySqlCommand("command to execute",conn))
{
//Code here..
}
}
I am working on a unit of work class and I'm curious how the connection should be handled. My repositories take in a unit of work, and use that connection for Get() commands.
Obviously, Commit() will handle all Add, Updates and Deletes. This would open the connection and begin the transaction and close when finished. How should Gets be handled?
Should the UOW, open the connection in the constructor and close when completely finished? Meaning while I pass UOW from repo to repo, the connection is open. Or should I be opening and closing it only as needed?
Approach #1: Unit of work opens connection and connection remains open until processing is finished?
public UnitOfWork(IDbConnection connection)
{
Connection = connection;
Connection.Open();
Transaction = Connection.BeginTransaction();
}
Approach #2: Snippet of a Get method that opens right before read and closes right after. If passing to multiple repos, same connection is used, just opened and closed a bunch.
using (var reader = manager.GetReader())
{
UOW.Connection.Open();
while (reader.Read())
list.Add(factory.CreateTFromReader(reader));
UOW.Connection.Close();
}
No, you should always open the connection when needed and be absolutely sure to close it when the work is complete. The Connection Pooling mechanism will take care of keeping the connection available for your current user or for other users connecting concurrently on the same server
I think also that the second example is not quite right. You should have something like this
using (IDbConnection cn = manager.GetConnection)
using (var reader = manager.GetReader())
{
cn.Open();
while (reader.Read())
list.Add(factory.CreateTFromReader(reader));
}
This will ensure that the connection is closed even in the event of exceptions, and that is returned to the pool in order to be reused
Connection Pooling
I am having difficulty in reading data from my SQLite database from MonoTouch.
I can read and write without any difficulty for the first few screens and then suddenly I am unable to create any further connections with the error:
Mono.Data.Sqlite.SqliteException: Unable to open the database file
at Mono.Data.Sqlite.SQLite3.Open (System.String strFilename, SQLiteOpenFlagsEnum flags, Int32 maxPoolSize, Boolean usePool) [0x0007e] in /Developer/MonoTouch/Source/mono/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/SQLite3.cs:136
at Mono.Data.Sqlite.SqliteConnection.Open () [0x002aa] in /Developer/MonoTouch/Source/mono/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/SQLiteConnection.cs:888
I ensure that i dispose and close every connection each time i use it but still i have this problem. For example:
var mySqlConn = new SqliteConnection(GlobalVars.connectionString);
mySqlConn.Open();
SqliteCommand mySqlCommand = new SqliteCommand(SQL, mySqlConn);
mySqlCommand.ExecuteNonQuery();
mySqlConn.Close();
mySqlCommand.Dispose();
mySqlConn.Dispose();
I'm guessing that I'm not closing the connections correctly. Any help would be greatly appreciated.
I'm pretty sure you guess is right. However it's pretty hard to guess what went wrong (e.g. what's defined in your connectionString will affect how Sqlite is initialized and will work).
From your example you seem to be disposing the SqliteConnection correctly but things could still go wrong. E.g. if some code throws an exception (and you catch them somewhere) then the Dispose call might never be called. It would be safer to do something like:
using (var mySqlConn = new SqliteConnection(GlobalVars.connectionString) {
mySqlConn.Open();
using (SqliteCommand mySqlCommand = new SqliteCommand(SQL, mySqlConn)) {
mySqlCommand.ExecuteNonQuery();
// work with the data
}
mySqlConn.Close();
}
That would ensure that the automagically finally clauses will dispose of the instance you create.
Also you might want to consider reusing your (first) connection instance, e.g. opening it once and re-use it everywhere in your application. OTOH you need to be aware of threading in this case (by default, you can change it, each connection is only safe to use on the thread that has created it).
Reusing could help your app performance but it also does not really fix your issue (but it might hide it). So I suggest you try to debug this first:
Using MonoDevelop you can set a breakpoint on line #136 on the /Developer/MonoTouch/Source/mono/mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/SQLite3.cs file (which is included with your MonoTouch installation) to see the actual n error code (before it gets translated to a string).
You can also set breakpoints on the dispose code to ensure it gets executed (and does not return errors). The number of connection creations and disposals should match. If not then use the Call Stack to see who's opening without closing.
I would suggest using the "using" block..That will make sure that everything is disposed off correctly and also that you are not closing connections when it is already closed..
using (SqliteConnection conn = new SqliteConnection(GlobalVars.connectionString))
{
conn.Open ();
SqliteCommand command = new SqliteCommand (conn);
.............
}
OK - i've got it working now by moving the close and dispose into a "finally".
var mySqlConn = new SqliteConnection (GlobalVars.connectionString);
mySqlConn.Open ();
try {
// CODE HERE
} finally {
mySqlConn.Close();
mySqlConn.Dispose();
}
I am creating desktop application in winform that will use Sqlite Database.
So I created Sqlite Helper class that uses System.Data.SQLite and each method of that Helper class opens and closes connection.
But now I also added ability to attach additional databases but after Connection is Closed, all attached databases gets lost.
To correct this I modified the class so that the connection is opened in constructor and remains open.
After the application ends, I want that connection to close without explicitly calling the Close method.
Any suggestions how to do that?
Keeping the connection open for the lifetime of your application is not a good way to go.
I suggest to not follow this route.
On the contrary, I will try to encapsulate the functionality to attach a database inside a method that could be called on the need to use basis.
For example:
private static void AttachDB(string fileDB, string aliasName, SQLiteConnection cn)
{
string sqlText = string.Format("ATTACH '{0}' AS {1}", fileDB, aliasName)
SQLiteCommand cmd = new SQLiteCommand(sqlText, cn)
cmd.ExecuteNonQuery();
}
then in your code
using(SQLiteConnection cn = new SQLiteConnection(GetConnectionString()))
{
AttachDB(#"C:\SQLite\UserData.sqlite3", "UserData", cn);
// Do your code here
}
Close should not disconnect your database but this will only work when .NET connection pooling mechanism is on. Make sure you have that enabled in your connection string:
Data Source=filename;Version=3;Pooling=True;Max Pool Size=100;
Depending on how your class is defined, you can use Dispose or a destructor. Or, explicitly call Close() at the end of the program (from within Main, after Run...).
In C# there is a special syntax for such situation:
using(var connection = new Connection())
{
//work with connection
}
it compiles to something like:
Connection connection = null;
try
{
connection = new Connection();
//your operations
}
finally
{
connection.Dispose();
}
on calling Dispose() you close connection.
At the moment our code looks like this
public void Close(bool saveChange)
{
if ((_Connection != null) && (_Connection.State == System.Data.ConnectionState.Open))
{
_Connection.Close();
_Connection.Dispose();
_Connection = null;
GC.Collect();
}
}
Where GC.Collect() is needed to close file properly and remove all .ldb files.
Is it possible to close db file and immideately remove all temp .ldb files without calling GC ?
As every class implementing IDisposable, you should use the using-statement to dispose objects. On this way connections are also getting closed.
For example:
using(var conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + Server.MapPath("Pets/Pets.mdb")))
{
conn.open();
// do something with it
}
You should also read this because the way you're using connections can be improved.
As a rule of thumb: always create,open,use and close connections at the same place and let the ADO.NET connection pool manage the underlying connections.
If you have a Class that is using the Data in several entry-points.
and you HAVE to keep the connection open.
(hence can not use using(Connection x=...){} statement)
.
your class should also inherit IDisposable and implement
void Dispose()
{
this.dbConnection.Dispose();
}
the dbConnection.Dispose() will take care of closing the connection gracefully unless you need some custom actions performed (e.g. Logout, Save Cached Info, Etc...)
Anyway, i am in favor of #Tim Schmelter idea:
Close the connection after any transaction.
The Connections will be cached in the Connection Pool => insignificant performance impact.
Calling GC.Collect() may not be the best solution, as this method collects all the "garbage". You may find it very helpful to make use of the using keyword. e.g.
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
connection.Open();
// Do work here.
}
Just right after your using block, the connection object will be disposed!
using connections, msdn
using keyword, msdn
connection.Close();
OleDbConnection.ReleaseObjectPool();
This solved it for me eventually