WCF Service References are IDisposables!

by Larry Spencer Saturday, December 8, 2012 10:48 AM

Consultant Ben Day tells the story of a Web application "with all the hardware you could possibly want" that became so slow as to be unusable when only 20 users were logged on. It was an ordinary application, but with one pervasive flaw: the SQL connections were not being closed. The developers had thought that the .NET garbage collector would Dispose() and therefore Close() their connections just fine. Not so. The garbage collector runs on a low-priority thread and it was not keeping up. Ben was able to make the system performant by packaging each SQL connection in a using block.

Disposing WCF Service References

Something similar can happen with WCF service references. The problem is often overlooked, perhaps because Microsoft's own tutorial suggests you make code like this:

 

private void button1_Click(object sender, EventArgs e)
{
    ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
    string returnString = client.GetData(textBox1.Text);
    label1.Text = returnString;
}

 

We'll overlook the horrible naming practices because the tutorial was about WCF, not naming. However, if you climb up the inheritance tree from Service1Client, you'll see that it's an IDisposable. Therefore, we should really do this:

 

private void button1_Click(object sender, EventArgs e)
{
    using (ServiceReference1.Service1Client client = new ServiceReference1.Service1Client())
    {
        string returnString = client.GetData(textBox1.Text);
        label1.Text = returnString;
    }
}

 

IDisposables and Service-Oriented Architecture

A "best practice" in service-oriented architecture (e.g., with WCF) is to "program to the interface." That lets us do things like mock the service when unit-testing a class that consumes it.

In Microsoft's example, the Service1Client class inherits from an interface, IService1. If their tutorial were to take just one more step toward true service orientation, they would have made the client variable an interface:

 

private void button1_Click(object sender, EventArgs e)
{
    using (ServiceReference1.IService1 client = new ServiceReference1.Service1Client())
    {
        string returnString = client.GetData(textBox1.Text);
        label1.Text = returnString;
    }
}

 

But wait! That won't compile! IService1 is not an IDisposable, so the compiler won't allow the using keyword. Do we have to choose between true SOA and cleaning up after ourselves? In the next post, I'll offer some ways to escape this conundrum.

Tags: , , ,

All | Dependency Injection | WCF

About the Author

Larry Spencer

Larry Spencer develops software with the Microsoft .NET Framework for ScerIS, a document-management company in Sudbury, MA.