June21

SqlBulkCopy should implement IDisposable

Ran into this issue today and wanted to write it down for others to hopefully find and save them some time in the future.

IDisposable means you need to cleanup, or does it?

If you use the SqlBulkCopy class (from System.Data.SqlClient) you would think that the object does not need to be cleaned up because it does not implement implicitly IDisposable, but you would be wrong.  Take a look in your favorite .net de-compiler at the Close method.

public void Close()
{
if (this._insideRowsCopiedEvent)
{
throw SQL.InvalidOperationInsideEvent();
}
this.Dispose(true);
GC.SuppressFinalize(this);
}

Notice that call to this.Dispose.  It is private, you can’t actually call it.  

It does implement the method explicitly, but you need to cast it ((IDisposable)bcp).Dispose() to get at the method.

So what?

I can hear some people already saying it.  Why should you care?  First because this is the meaning of having a pattern like dispose, you can be sure that things needing extra cleanup will let you know about it.

The bigger reason is that if you use the UseInternalTransaction option you end with a strange error later on in your program (usually when trying to cleanup your connection pool which was in a using statement).

Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.

The statement has been terminated.

What the heck does that mean?  Basically the transaction created internally by the bulk copy class was never closed.  Silly me, I assumed that if it wanted me to clean it up then Dispose would have been implemented.  The only way to fix this is to put a try / finally around your code block and explicitly call Close() on the bulk copy instance you allocated.

Since there are unmanaged resources under the hood in the class you need to make sure you clean it up!

No special knowledge required

Requiring a user to have some sort of special knowledge about your internals is a bad practice.  It is hard enough to get users to cleanup through using statements because they think the runtime should handle it for them.  Please remember to put hints for your users (like IDisposable) to let them know the right thing to do with your classes.

Comments (1) -

22/06/2011 12:55 #

Dan

I completely agree. Before 2.0, there were some reader objects in System.IO that had the same problem. There was a .Close() method but did not implement IDisposable. I think they fixed all of those. Looks like the same situation here.

Dan

Pingbacks and trackbacks (1)+

Comments are closed