I have been unable to find any documentation on properly closing database connections in WCF service operations. I have a service that returns a streamed response through the following method.
public virtual Message GetData()
{
string sqlString = BuildSqlString();
SqlConnection conn = Utils.GetConnection();
SqlCommand cmd = new SqlCommand(sqlString, conn);
XmlReader xr = cmd.ExecuteXmlReader();
Message msg = Message.CreateMessage(
OperationContext.Current.IncomingMessageVersion,
GetResponseAction(),
xr);
return msg;
}
I cannot close the connection within the method or the streaming of the response message will be terminated. Since control returns to the WCF system after the completion of that method, I don’t know how I can close that connection afterwards. Any suggestions or pointers to additional documentation would be appreciated.
Good question, actually. Unfortunately, one for which I believe there is no good answer. There’s actually an active Microsoft Connect ticket about this very issue.
Normally, if you want to stream results and you just need a regular
SqlDataReader, you can use theExecuteReaderoverload that takes aCommandBehavior, and specificallyCommandBehavior.CloseConnection. If a reader is created using this command behavior, then when youClose(orDispose) the reader, it also closes the underlying connection, so you never have to worry about disposing theSqlConnection.Unfortunately, there’s no equivalent overload of
ExecuteXmlReader. You have to dispose theSqlConnectionexplicitly.One way around this would be to implement your own
XmlReaderdescendant, wrapping the realXmlReaderobtained fromExecuteXmlReaderand forcing the connection closed on close.The basic idea is just to derive from
XmlReaderand wrap both the realXmlReaderand theSqlConnectionitself. Something like this:This takes the connection and the reader directly from the
SqlCommandso there’s no chance of a connection/reader mismatch. You need to implement the rest of theXmlReadermethods and properties too – it’s just a lot of boring method proxying:Dull, dull, dull, but it works. This reader will close the connection for you when it’s done, same as a
SqlDataReaderopened withCommandBehavior.CloseConnection.Last thing to do would be to create an extension method to make this easier to use:
Once you have this, instead of writing:
You write:
That’s it. Now when WCF closes your reader, it will automatically close the underlying connection.
(Disclaimer: This hasn’t officially been tested, but I can see no reason why it wouldn’t work, unless WCF does not actually close the reader. Be sure to actually test this against a live SQL connection to make sure that it really doesn’t leak connections.)