views:

377

answers:

5

Suppose that I have the following code:

private void UpdateDB(QuoteDataSet dataSet, Strint tableName)
{
    using(SQLiteConnection conn = new SQLiteConnection(_connectionString))
    {
        conn.Open();
        using (SQLiteTransaction transaction = conn.BeginTransaction())
        {
            using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM " + tableName, conn))
            {
                using (SQLiteDataAdapter sqliteAdapter = new SQLiteDataAdapter())
                {
                    sqliteAdapter.Update(dataSet, tableName);
                }
            }
            transaction.Commit();
        }
    }
}

The C# documentation states that with a using statement the object within the scope will be disposed and I've seen several places where it's suggested that we don't need to use try/finally clause.

I usually surround my connections with a try/finally, and I always close the connection in the finally clause. Given the above code, is it reasonable to assume that the connection will be closed if there is an exception?

A: 

You can assume that the connection will be closed if you get an exception.

MadBoy
+4  A: 

Yes, you either need to use a try/finally or a using statement. You don't need both.

A using statement is almost the same as a try/finally except that in C# 3 you can't reassign to the variable inside the using block.

using (IDisposable d = foo())
{
     d = null; // Error:  Cannot assign to 'd' because it is a 'using variable'
}

Previously you could reassign but the original object would still be disposed, not the newly assigned object and you would also get this compile warning:

Possibly incorrect assignment to local 'd' which is the argument to a using or lock statement. The Dispose call or unlocking will happen on the original value of the local.

Mark Byers
+2  A: 

Yes, the using statement is pretty much just shorthand for a try ... finally block.

For example, this code...

using (MyDisposableType foo = new MyDisposableType())
{
    foo.DoSomething();
}

...would equate to the following...

{
    MyDisposableType foo = new MyDisposableType();
    try
    {
        foo.DoSomething();
    }
    finally
    {
        if (foo != null)
            ((IDisposable)foo).Dispose();
    }
}
LukeH
A: 

Using() ensures that the item instantiated within the parameters will be disposed of regardless of that happens within the associated code block. This includes closing the database connection assuming that SQLiteConnection handles its disposal correctly.

David Lively
+5  A: 

You are correct; the using statement compiles to a try / finally block.

The compiler transforms using(resource) statement; into the following code:

{
   ResourceType resource = expression;
   try {
      statement;
   }
   finally {
      if (resource != null) ((IDisposable)resource).Dispose();
   }
}

(The cast to IDisposable is in case ResourceType implements IDisposable explicitly.

SLaks