views:

781

answers:

3

I've had a suspicion that a database connection used in one of our applications is not always closed. I went to see the code and I've found a class DataProvider that has SqlConnection object. The connection is opened in the constructor of this class and closed in it's Dispose method (don't judge that, i know keeping an open connection is evil, it's just not my code and it's not the point of the question anyway). Dispose method is implemented like this:

protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    if (_conn != null)
                        _conn.Close();
                }

                _disposed = true;
            }
        }

The question is: does it always guarantee that the connection is closed? And is this code right? I think there should be _conn.Dispose() called - am I right and could it affect not closing the connection (probably not)?

A: 

I think you should take it to your destructor method, and you should add a line that checks if the connection is not closed :

class YourClass
{
    ~YourClass()
    {
        if (_conn != null && _conn.State != ConnectionState.Closed )
        {
            _conn.Close();
        }
    }
}

Here is a paragraph on using dispose or destructor from MSDN :

If your application is using an expensive external resource, we also recommend that you provide a way to explicitly release the resource before the garbage collector frees the object. You do this by implementing a Dispose method from the IDisposable interface that performs the necessary cleanup for the object. This can considerably improve the performance of the application. Even with this explicit control over resources, the destructor becomes a safeguard to clean up resources if the call to the Dispose method failed.

Canavar
There is no such thing as a "Destructor" in C# - do you mean "Finalizer"? Also, please explain why it is better in the finalizer?
1800 INFORMATION
I updated my question about destructors and dispose. you can see MSDN uses destructor for a class finalizer.
Canavar
You will not need to implement a finalizer, since a SqlConnection already implements a finalizer trough one of its base classes (System.ComponentModel.Component). This could actually negatively impact performance.
Dries Van Hansewijck
@Dries: Absolutely - don't create a finalizer unless you've got a *direct* handle reference (and then try to use SafeHandle instead anyway). It should be very, very rare that you need to write a finalizer these days - unless it's only in debug mode, to indicate that you haven't disposed of something properly. -1 from me I'm afraid.
Jon Skeet
+1  A: 

conn.Dispose(); will also close the connection, so can't hurt changing it to follow the dispose pattern.

But there functionally equivalent so there must be a problem else where.

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.close.aspx

If the SqlConnection goes out of scope, it won't be closed. Therefore, you must explicitly close the connection by calling Close or Dispose. Close and Dispose are functionally equivalent. If the connection pooling value Pooling is set to true or yes, the underlying connection is returned back to the connection pool. On the other hand, if Pooling is set to false or no, the underlying connection to the server is closed.

Hath
+2  A: 

Dispose is never called automatically.

The connection will not be closed until the Dispose method of your object is explicitly called, or if your class in used in a using() block

A safer way is to call the dispose method in your finalizer and ensure the finalizer is suppressed when the Dispose method is called.

This article present the correct way to implement the pattern

Hope it helps !

Cédric

Cédric Rup
ok but if the application is closed (normally or by an error) the dispose method will be called and the connection will be closed?
agnieszka
When your application is shut down, all finalizers should be called by the garbage collector, so at least the connections will be closed as the finalizer of the Connection objects will be triggered... but that's a lame way to close a connection ;o)
Cédric Rup
And by the way : Dispose method are never called automatically. In your current state of code, connections are closed because the dispose method of Connection is called in their finalizers
Cédric Rup
i know, it's not my code as i already said ;)
agnieszka
do you mean that this method will be never called anyway?
agnieszka
If not explicitly called in code, not called by the finilizer or eventually by an ancestor's, nor being called at the end of a using() block, this method will never be called
Cédric Rup
ok i've finally read about it in msdn and yes, they say Dispose is for explicit releasing of resources and that yo ushould implement finalizer to ensure the resources are always released. didn't know that. thanks!
agnieszka
-1: "A safer way is to call the dispose method in your finalizer" - a finalizer won't make any difference and probably shouldn't be implemented in the DataProvider class as it doesn't have any unmanaged resources. If DataProvider implements IDisposable, the OP's code is OK, and callers need to dispose the DataProvider instance.
Joe
@joe: Do you mean that there's no need of finalizer in this class because the connection will be unreferenced at the same time than the Data provider object and so the finalizer of the connection will be called be GC, thus closing the connection ?
Cédric Rup
I mean that if DataProvider implements IDiposable properly, it shouldn't be calling _conn.Close() or _conn.Dispose() in a finalizer, because _conn is a managed resource. So adding a finalizer has no benefit. In general a finalizer should only be implemented in the rare cases when a class owns an unmanaged resource directly.
Joe
Cedric, below is a note got from MSDN:Do not call Close or Dispose on a Connection, a DataReader, or any other managed object in the Finalize method of your class. In a finalizer, only release unmanaged resources that your class owns directly. If your class does not own any unmanaged resources, do not include a Finalize method in your class definition. For more information, see Programming for Garbage Collection.but you said:A safer way is to call the dispose method in your finalizer and ensure the finalizer is suppressed when the Dispose method is called.
odiseh
@odiseh : I agree with you and Joe, that's what i meant in my initial answer (maybe not correctly stated I guess ;o). In fact, the Dispose pattern is quite complex : it must be implemented on different ways depending on the class hierarchy, the type of resource held etc... most comprehensive and complete article I found is there http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=88e62cdf-5919-4ac7-bc33-20c06ae539ae
Cédric Rup