I have a question about closing an opened connection to a database in C#. Let's say we abandon the "using" method and use a try/catch/finally block to open and close the connection.
try
{
connection = new SqlConnection();
connection.Open();
}
catch (Exception ex)
{
// Do whatever you need with exception
}
finally
{
1.connection.Dispose();
2.if (connection != null)
{
connection.Dispose();
}
}
My question here is what exactly happens if only 1) in this code segment occurs. The connection should always be checked for null before disposed(closed), but what if it isn't, and we try to close a connection object that's null? (I'm interested in what happens to the opened connection, can this lead to a leak)
In the question, if connection.Dispose() is called on a null connection without the check, you cause a new exception that has not been handled, and everything that goes with that. Additionally, if this was done because the connection variable was set to null before the finally block without ensuring the connection was closed, it is possible to leak that open connection ... though as a practical matter it's rare to see code in the wild that knows to use a finally but also wants to set the connection to null.
Granting the lack of using (which is suspect, but whatever), I prefer this pattern:
finally
{
if (connection is IDisposable) connection.Dispose();
}
This still protects against null values* in the connection object, and is a closer mimic for what the using pattern was already doing behind the scenes.
Note, however, you're still missing one important feature of a using block, which is protection against something assigning null to your variable before the block closes. using blocks also protect your connection in a separate (hidden) variable, so you're sure you still have a valid reference at the end of the block (this is new in C# 8).
*(For completeness, the author of that linked tweet is the lead on the C# compiler team, so he should know, and he's not being ironic).
Related
I have a C# application that reads/writes from/to an Access Database. I do this using an OleDbConnection.
Before a read / write, I want to check that my database connection is open. It should be straight-forward....
if (Connection.State != ConnectionState.Open) Connection.Open();
While this generally works well, it is not working for situations where network access is interrupted. The Connection.State is still recorded as 'Open', so I'd get an exception. So, I tried this:
Connection.ResetState();
if (Connection.ConnectionState(DatabaseType) != ConnectionState.Open) Connection.Open();
Nope... That's not working either, as the ResetState() method isn't actually resetting the state.
So I tried this extension method (a bit ugly...)
public static ConnectionState ConnectionState(this OleDbConnection connection, DatabaseType type)
{
connection.ResetState();
if (type == DatabaseType.Access)
{
//Reset state might not work... Check that the datasource is locatable
if (!File.Exists(connection.DataSource)) return System.Data.ConnectionState.Closed;
return connection.State;
}
return connection.State;
}
This "sort of" works, in that it correctly identifies that the DataSource can't be located. But then I get an exception when I try to open the database; not that it can't be found, but that its an invalid operation trying to open a connection that is already open!
I've spent about an hour trying to google to find a reliable way to get the true status of the database connection. Any other suggestions?
Correct way to use DbConnection is to create a new one for every command. Connection pooling means there is not usually a big overhead, and any network issues in between are sorted out automatically.
Make sure to Dispose correctly.
I think that it's not necessary in this case (although I know we can use using for the transaction as well as for the session). Here is the code I'm wondering about:
using(var session = _sessionFactory.OpenSession()){
session.BeginTransaction();
try {
//some code
session.Transaction.Commit();
} catch(Exception ex){
session.Transaction.Rollback();
}
}
Is there any leakage for the code above? I know it would seem to be better to write it like this:
using(var session = _sessionFactory.OpenSession()){
using(var t = session.BeginTransaction()){
try {
//some code
t.Commit();
} catch(Exception ex){
t.Rollback();
}
}
}
However as I said, I wonder about the necessity to dispose the transaction explicitly as well. Please advise. Btw do the above code is safe enough (using/closing right away) to use for polling data such as every second? Can it bombard with increasing opened connections to the target database? I don't think keeping a long-opening connection is good in any case.
Check the documentation here microsoft docs
Calling this method marks the end of the transaction scope. If the TransactionScope object created the transaction and Complete was
called on the scope, the TransactionScope object attempts to commit
the transaction when this method is called. In this case, this method
blocks until the first phase of transaction processing is complete.
The first phase ends after all resource managers and enlistments in
the transaction have voted on the transaction outcome and the
TransactionManager has durably decided to commit or abort the
transaction. The second phase of processing is always asynchronous.
Therefore, there is no guarantee that data just committed from within
a given transaction will be immediately available afterwards when not
using another transaction to view this data.
The use of the C# using construction ensures that this method is
called even if an exception occurs. Exceptions that occur after
calling this method may not affect the transaction. This method also
restores the ambient transaction to it original state. A
TransactionAbortedException is thrown if the transaction is not
actually committed.
In truth, this would be the exact same thing with having a finally clause with dispose command in it only. But you can never be sure that the next developer will not do something like this:
using(var session = _sessionFactory.OpenSession()){
using(var t = session.BeginTransaction()){
try {
//some code
t.Commit();
} catch(Exception ex){
// Code the throws exception
t.Rollback();
} finally {
// Some other code that throws exception
// And then dispose
}
}
}
So instead of syntactic sugar, this also helps make sure that whatever happens everything is disposed correctly.
You can check the code here
https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Impl/
In SessionImpl.cs you will find that the code does nothing to close and/or dispose the transaction.
sc is a SQL connection passed in from the calling function
I'm using one SQL connection throughout my entire program and having each subfunction open and close it as needed. (I read this was fine, because the SQLConnection class has it's own connection pooling functionality)
string q = "this would be a query";
using (SqlCommand cmd = new SqlCommand(q, sc))
{
cmd.Parameters.Add("#ID", SqlDbType.Int);
cmd.Parameters["#ID"].Value = (an id that is passed in);
try
{
sc.Open();
using (var reader = cmd.ExecuteReader())
{
if(reader.read())
{ logic that might throw exception }
else
{ logic that might throw exception }
}
sc.Close();
}
catch (Exception e)
{
alert user, program does not halt but current function returns
}
}
So the connection opens and the command attempts to execute and some logic is performed that might throw an exception. (I'm not expecting it to) This function is part of a larger program that is processing a large dataset. If it fails DUE TO AN EXCEPTION it needs to note it, but it also needs to attempt to keep running.
Other parts of the program are sharing this connection and opening and closing it as they need it and I've used this basic template for all queries in the program.
It just occurred to me that if an exception occurred, the connection might not be closed. Am I correct in thinking that? My original concern when writing this is that the sc.Open() would be the thing that would throw an exception, but as I've used this in multiple places I've realized that this was short sighted because the connection could open and then any number of steps between the close could throw an exception.
Do I need additional logic here to make sure this connection is closed and the program can attempt to continue running?
If my understanding is correct that the connection needs to be closed in the event of an exception between the open and close I think I have 2 options :
try/catch between the open and close
sc.Close() in the catch block (Bonus concern : If the sc.Open() throws an exception and catch block tries to sc.Close() will an additional exception be thrown?)
You do not need to worry about closing the connection. The connection is closed automatically when it disposed by the using statement within which the connection is created.
In the event of an exception, the connection will still be disposed (and thus closed) because that's how a using statement is designed to work.
You have the State property of the SqlConnection that you can use to determine what state the last network operation left the connection in. This property is described here: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.state(v=vs.110).aspx
I would recommend reacting to exceptions in the SqlConnection (such as Open) and in the SqlCommand separately, because, in my experience, you will usually want to take different actions. Even with the overall approach you want to take,
if you can't open your connection, there is no point in preparing the query,
and you likely want to say something different about inability to open the connection than you would if the query failed. I would move the sc.Open() before the creation of the SqlCommand and try/catch around that.
Clarification on the above answer by #roryap - there is no need for sc.Close() if your connection is created in a using statement but from your question I guess it's not. In which case you should probably add a finally section to the try catch block and close the connection in there.
Its better that you close the connection in finally block
finally
{
sc.Close();
}
After try block is completed, the finally block will work.
In a case of an exception, finally block also works.
So the connection will closed in any case.
I tried to search for this on SO but couldn't find it. Maybe I didn't search properly and it is a duplicate of something.
But I would like to ask a question: what is the difference between opening a DB connection inside a using(...) block and outside.
For clarify what I mean, look at the code snippets below.
Snippet where we open a DB connection outside "using" block:
if (_dbConn.State != ConnectionState.Open)
_dbConn.Open();
using (var oraclePackage = new OraclePackage())
{ // some DB function here... }
Snippet in which a DB connection is opened inside a "using" block:
using (var oraclePackage = new OraclePackage())
{
if (_dbConn.State != ConnectionState.Open)
_dbConn.Open();
// some DB functions here
}
Would the block where I DO NOT open a connection inside "using" still close it in case of an exception or would it be left open?
Would the block where I DO NOT open a connection inside "using" still close it in case of an exception or would it be left open?
In both of those examples, the connection would still be open, until perhaps a finaliser ran, if one ever did. Neither has a using that is "using" dbConn.
The code:
using(someObject)
{
// More code here.
}
Is equivalent to:
try
{
// More code here.
}
finally
{
if(someObject != null)
((IDisposable)someObject).Dispose();
}
And the code:
using(var someObject = new SomeClass())
{
// More code here.
}
Is equivalent to:
var someObject = new SomeClass();
try
{
// More code here.
}
finally
{
if(someObject != null)
((IDisposable)someObject).Dispose();
}
(Null checks might be optimised out in cases where the object clearly cannot be set to null at any point).
Your code does this with oraclePackage so oraclePackage will be guaranteed to have Dispose() called on it, whether the block of code is left due to an exception or not. You code does not do this with dbConn.
As such, if you don't explicitly call dbConn.Dispose() or dbConn.Close() (which dbConn.Dispose() almost certainly calls into) the connection will not be closed.
If there are no remaining GC roots that can access dbConn then it's likely that eventually the internal object that represents the actual open connection will be finalised, which will lead to the connection being closed, but this is not guaranteed to happen or to happen in a timely manner, and it is quite likely not to work as well with the internal caching mechanism most IDbConnection implementations use.
As you are not applying using on connection object the connection will remain open if exception occurs...so you need finally block which close your connect even there is exception.
so your code will be , as you are not applying using on connection object
try
{
using (var oraclePackage = new OraclePackage())
{
if (_dbConn.State != ConnectionState.Open)
_dbConn.Open();
// some DB functions here
}
}
finally
{ _dbConn.Close(); }
Using statement does not handle any exceptions. It is responsible for calling IDisposable on current object (DB connection).
This means that no matter if you open connection inside or outside the using block, at the end of the block the connection will be disposed
I just had a pretty painful troubleshooting experience in troubleshooting some code that looked like this:
try {
doSomeStuff()
doMore()
} finally {
doSomeOtherStuff()
}
The problem was difficult to troubleshoot because doSomeStuff() threw an exception, which in turn caused doSomeOtherStuff() to also throw an exception. The second exception (thrown by the finally block) was thrown up to my code, but it did not have a handle on the first exception (thrown from doSomeStuff()), which was the real root-cause of the problem.
If the code had said this instead, the problem would have been readily apparent:
try {
doSomeStuff()
doMore()
} catch (Exception e) {
log.error(e);
} finally {
doSomeOtherStuff()
}
So, my question is this:
Is a finally block used without any catch block a well-known java anti-pattern? (It certainly seems to be a not-readily-apparent subclass of the obviously well-known anti-pattern "Don't gobble exceptions!")
In general, no, this is not an anti-pattern. The point of finally blocks is to make sure stuff gets cleaned up whether an exception is thrown or not. The whole point of exception handling is that, if you can't deal with it, you let it bubble up to someone who can, through the relatively clean out-of-band signaling exception handling provides. If you need to make sure stuff gets cleaned up if an exception is thrown, but can't properly handle the exception in the current scope, then this is exactly the correct thing to do. You just might want to be a little more careful about making sure your finally block doesn't throw.
I think the real "anti-pattern" here is doing something in a finally block that can throw, not not having a catch.
Not at all.
What's wrong is the code inside the finally.
Remember that finally will always get executed, and is just risky ( as you have just witnessed ) to put something that may throw an exception there.
There is absolutely nothing wrong a try with a finally and no catch. Consider the following:
InputStream in = null;
try {
in = new FileInputStream("file.txt");
// Do something that causes an IOException to be thrown
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// Nothing we can do.
}
}
}
If an exception is thrown and this code doesn't know how to deal with it then the exception should bubble up the call stack to the caller. In this case we still want to clean up the stream so I think it makes perfect sense to have a try block without a catch.
I think it's far from being an anti-pattern and is something I do very frequently when it's critical do deallocate resources obtained during the method execution.
One thing I do when dealing with file handles (for writing) is flushing the stream before closing it using the IOUtils.closeQuietly method, which doesn't throw exceptions:
OutputStream os = null;
OutputStreamWriter wos = null;
try {
os = new FileOutputStream(...);
wos = new OutputStreamWriter(os);
// Lots of code
wos.flush();
os.flush();
finally {
IOUtils.closeQuietly(wos);
IOUtils.closeQuietly(os);
}
I like doing it that way for the following reasons:
It's not completely safe to ignore an exception when closing a file - if there are bytes that were not written to the file yet, then the file may not be in the state the caller would expect;
So, if an exception is raised during the flush() method, it will be propagated to the caller but I still will make sure all the files are closed. The method IOUtils.closeQuietly(...) is less verbose then the corresponding try ... catch ... ignore me block;
If using multiple output streams the order for the flush() method is important. The streams that were created by passing other streams as constructors should be flushed first. The same thing is valid for the close() method, but the flush() is more clear in my opinion.
I'd say a try block without a catch block is an anti-pattern. Saying "Don't have a finally without a catch" is a subset of "Don't have a try without a catch".
I use try/finally in the following form :
try{
Connection connection = ConnectionManager.openConnection();
try{
//work with the connection;
}finally{
if(connection != null){
connection.close();
}
}
}catch(ConnectionException connectionException){
//handle connection exception;
}
I prefer this to the try/catch/finally (+ nested try/catch in the finally).
I think that it is more concise and I don't duplicate the catch(Exception).
try {
doSomeStuff()
doMore()
} catch (Exception e) {
log.error(e);
} finally {
doSomeOtherStuff()
}
Don't do that either... you just hid more bugs (well not exactly hid them... but made it harder to deal with them. When you catch Exception you are also catching any sort of RuntimeException (like NullPointer and ArrayIndexOutOfBounds).
In general, catch the exceptions you have to catch (checked exceptions) and deal with the others at testing time. RuntimeExceptions are designed to be used for programmer errors - and programmer errors are things that should not happen in a properly debugged program.
In my opinion, it's more the case that finally with a catch indicate some kind of problem. The resource idiom is very simple:
acquire
try {
use
} finally {
release
}
In Java you can have an exception from pretty much anywhere. Often the acquire throws a checked exception, the sensible way to handle that is to put a catch around the how lot. Don't try some hideous null checking.
If you were going to be really anal you should note that there are implied priorities among exceptions. For instance ThreadDeath should clobber all, whether it comes from acquire/use/release. Handling these priorities correctly is unsightly.
Therefore, abstract your resource handling away with the Execute Around idiom.
Try/Finally is a way to properly free resources. The code in the finally block should NEVER throw since it should only act on resources or state that was acquired PRIOR to entry into the try block.
As an aside, I think log4J is almost an anti-pattern.
IF YOU WANT TO INSPECT A RUNNING PROGRAM USE A PROPER INSPECTION TOOL (i.e. a debugger, IDE, or in an extreme sense a byte code weaver but DO NOT PUT LOGGING STATEMENTS IN EVERY FEW LINES!).
In the two examples you present the first one looks correct. The second one includes the logger code and introduces a bug. In the second example you suppress an exception if one is thrown by the first two statements (i.e. you catch it and log it but do not rethrow. This is something I find very common in log4j usage and is a real problem of application design. Basically with your change you make the program fail in an way that would be very hard for the system to handle since you basically march onward as if you never had an exception (sorta like VB basic on error resume next construct).
try-finally may help you to reduce copy-paste code in case a method has multiple return statements. Consider the following example (Android Java):
boolean doSomethingIfTableNotEmpty(SQLiteDatabase db) {
Cursor cursor = db.rawQuery("SELECT * FROM table", null);
if (cursor != null) {
try {
if (cursor.getCount() == 0) {
return false;
}
} finally {
// this will get executed even if return was executed above
cursor.close();
}
}
// database had rows, so do something...
return true;
}
If there was no finally clause, you might have to write cursor.close() twice: just before return false and also after the surrounding if clause.
I think that try with no catch is anti-pattern. Using try/catch to handle exceptional conditions (file IO errors, socket timeout, etc) is not an anti-pattern.
If you're using try/finally for cleanup, consider a using block instead.