Monday, September 14, 2009

IIS 6 Native Compression

IIS 6 allows compression of messages sent to client requests. The following explains how to enable compression/decompression using gzip.


  • Open IIS Inetmgr.
  • Right click on "Web Sites" and then click the service tab.
  • Check "Compress application files" and "Compress static files" under HTTP compression.
  • Click OK
  • Click "Web Service Extensions"
  • Add the gzip.dll extension

Note: Adding a web service extension allows IIS to utilize a program (in this case gzip). By default IIS only serves up static content, and you will see the ASP and ASP.NET 1.1 and 2.0 are likely currently configured on most servers.


  • Navigate to C:\%Windir%\system32\inetsrv
  • Open MetaBase.xml
  • Find the IIsCompressionScheme nodes, and make sure it looks like the following:



  • Save and close.
  • Restart IIS.

Now that IIS Compression is enabled at the website level, you must opt-in for compression at a web service instance level:

MyWebService ws = new MyWebService()

ws.EnableDecompression = true;




Thats it, compression/decompression will automatically occur for this instance of this web service on all method calls.

Note: This information was generally gleaned from Scott Forsyth's blog (which I note below), however the specific metabase.xml settings that were necessary to make this work differed slightly, and are noted in the config snippet above.

Another Note: compression level is set to 9 based on the following:

"HcDynamicCompressionLevel has a default value of 0. Basically this means at if you did everything else right, the compression for dynamic contact is at the lowest level. The valid range for this is from 0 to 10. I had the opportunity of receiving an internal testing summary from Chris Adams from Microsoft regarding the compression level -vs- CPU usage which showed that the CPU needed for levels 0 - 9 is fairly low but for level 10 it hits the roof. Yet the compression for level 9 is nearly as good as level 10. I write all this to say that I recommend level 9 so make sure to change HcDynamicCompressionLevel to 9. Do this for both deflate and gzip." Source: http://weblogs.asp.net/owscott/archive/2004/01/12/57916.aspx




Thursday, July 2, 2009

SqlConnection.Dispose vs. SqlCommand.Dispose

After reviewing the service layer of an application to verify that all SqlConnections were properly being cleaned up, I thought I would post my findings on the details of how the SqlCommand and SqlConnection objects work with ADO.Net connection pooling.

I found several blogs/threads that stated "calling dispose on a SqlCommand instance will in turn clean up the underlying connection and remove it from the ADO.Net connection pool". This is not quite the case. I put performance monitor on task, and while watching NumberOfActiveConnections and NumberOfPooledConnections, it was clear that the active connection was never closed by calling SqlCommand.Dispose(). A review of MSDN documentation on the dispose method simply states: "Releases all resources used by the Component. (Inherited from Component.)".

To ensure that the active connection is in fact closed, and returned to the connection pool, you must call either Close() or Dispose() on the SqlConnection instance. It is recommended to call Dispose() since this also releases other instance level resources (such as the connection string). Note that even when calling Dispose, the connection is returned to the ADO.Net connection pool.

You can accomplish this same functionality by wrapping your connection/command in using statements, the underlying connection management is the same, and this accomplishes calling the Dispose() method on both the connection and command.



Friday, June 26, 2009

ADO.Net connection pooling and SQL Server 2005/2008 mirroring

ADO.Net connection pooling

Connection pools are stored within App Domain. For an IIS application, this will be within the app domain that is hosted within a specific w3wp.exe process (one per application pool). For a windows forms application, the connect pools are still stored at the App Domain level, within the process. A connection pool will be created per process/App Domain/executing user (in the case of integrated authentication)/connection string.



Per figure 1, you can see individual identical connections reside within connection pools, which in turn reside within a pool group. A pool group is merely a collection of connection pools that differ only by the executing user. Pool groups are in turn within an app domain within the executing process.

Since connection pools are hosted within an app domain, the lifetime of the connections is the same as the app domain.

SQL Server mirroring

To utilize SQL mirroring, add the “Failover Partner=[server name\instance name]” attribute to your connection string.

ADO.Net will manage determining that the principal server is the one named in the “Data Source” attribute initially.

If a connection pool has already been established within the current app domain when a failover to the mirrored server occurs, the following steps happen:

  1. A SqlException is raised with the message “A transport-level error has occurred when sending the request to the server….” Note: you must handle this raised exception, close the current connection and re-open the connection in order to handle the failover as smoothly as possible.
  2. Failover is detected by ADO.Net
  3. Failover partner is identified from connection string
  4. Pool groups are cleared
  5. New connection is created in a connection pool with a server name of the failover partner
If there are no current connections, ADO.Net will gracefully handle failing over to the mirrored server.