views:

629

answers:

4

In an answer to a previous question somebody recommended:

have the SqlConnection a member variable of your class, but make the class IDisposable and dispose of the SqlConnection when the class is disposed

I have put together an implementation of this suggestion (below) but wanted to check that this implementation is correct (obviously it doesn't currently do anything except open the connection but the idea is that there would be methods in there which would use the connection and which would be able to rely on it existing and being open).

public class DatabaseRecord : IDisposable
{
    protected SqlConnection connection;

    public DatabaseRecord()
    {
        connection = new SqlConnection("ConnectionString");
        connection.Open();
    }

    // IDisposable implementation

    private bool disposed;
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }


    private void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                connection.Dispose();
            }
            disposed = true;
        }

    }

    // Destructor
    ~DatabaseRecord()
    {
        Dispose(false);
    }
}

Will this work? Will classes which use instances of DatabaseRecord need to do anything special or will the Dispose automatically be called once the instances are no longer used/ referenced? Is this more efficient/ better than using using (var connection = new SqlConnection("...")) { } in each separate method body where the connection is needed?

+1  A: 

This will work and it will be more efficient that multiple using statements. The code that uses the DatabaseRecord class can do so inside a using statement to have it automatically cleaned up there when it leaves the loop.

One recommendation however, would be in the Dispose method to check the state of the Connection object and close it if it is still open before calling dispose.

Adam Gritt
Thanks for the reply :) I think that based on the amount of places these classes are used I would rather do the using inside the DatabaseRecord class even if it is a tiny bit less efficient.Re. closing the connection, as other people have mentioned there is logic to do that within SqlConnection.Dispose...
vitch
+3  A: 

SqlConnection is a managed resource, and should be disposed within the if (disposing) block. Classes using your class should dispose it, ideally witrh a using block. Whether this is better than individual using blocks for SqlConnections will depend on the other methods of this class and how they are used.

David M
Thanks for the answer. I thought that maybe the connection should be closed within the `if (disposing)` block (I've just edited the question now so it is based on your response) but in the end decided not because I wanted it to also be disposed when the destructor was called (obviously it doesn't work like that though!)...I was hoping that consumers of the class could be oblivious to the classes IDisposable nature. The fact that they need to use `using` or directly call `Dispose` nudges me back towards the other implementation (a seperate `using (new SqlConnection()){}` inside each method).
vitch
+2  A: 

connection.Dispose() should be moved to if (disposing) { ... } block. The calling of Close() is not required because Dispose() will close the connection when connection is open.

Andrey Shvydky
Thanks for the headsup - I fixed the code in the question :)
vitch
I have one more comment: why this class requires the destructor? Your class does not contains unmanaged resources so you should not implement destructor/Finalize() for it. Destructor will cause some GC performance penalties. Am I correct?
Andrey Shvydky
I don't know! I was hoping that the use of the destructor would prevent users of my classes from having to explictly `Dispose` it (or use `using`) but it seems that this isn't the case...
vitch
+2  A: 

All the advice I've seen says that DbConnections should be kept around for the minimum time, so the format I'd prefer to see in code I'm reviewing is

using (var connection = new SqlConnection("...")) { ... }
Rowland Shaw
That's the way I was originally approaching it and the approach that I am now leaning to again - thanks :)
vitch