Switched to Posterous

There's been a couple of changes lately. One of them is this blog moving to Posterous. I haven't written a worthwhile post in...years..and many of them have stale content. So I'm ditching most of them and re-posting a couple that seemed to have some value.

More later.

Comments [0]

Community Server: Single Sign-On in reverse

Community Server's Single-Sign-On modules handle the case where:

  • You have an ASP.NET website with an adjoining Community Server website
  • Members log into your main ASP.NET website and you want Community Server to recognize that site's authentication of the member

What if members log into your Community Server website but not your main ASP.NET website? Over the past week, I've encountered two people who want membership to be handled by Community Server. But their main website needs to determine whether the member is authenticated via User.Identity.IsAuthenticated and User.Identity.Name.

It's possible to do so. I tested the scenario where the main website is at www.yourdomain.com and the community is at community.yourdomain.com. Both sites use forms authentication.

In order for www.yourdomain.com to see the authenticated user, you must make sure that two elements within the web.config file of each website are compatible.

In the <forms> element of the <authentication> element, the protection attributes must have identical values and the path attributes must have compatible values. In the <machineKey> element, the validationKey, decryptionKey, and validation attributes must have identical values. The following example shows the elements:

<authentication mode="Forms">
 <
forms name=".CommunityServerpath="/" protection="Alltimeout="60000"
    loginUrl="CS login Url" slidingExpiration="true" />
</
authentication>

 <machineKey
  validationKey = " [your validation key]"
  decryptionKey = " [your decryption key]"
  validation = " SHA1" />

This is described with a little more detail in the .NET Framework Developer's Guide, topic Forms Authentication Across Applications.

SqlDataAdapter.Fill has slow performance

This post falls into the category of "Solution for a technical issue for which I found no help on the Internet".

Overview

If you're using adhoc SqlParameters with a SqlDataAdapter and notice that calls to the SqlDataAdapter's Fill method take longer than expected, try using a typed SqlParameter instead of an adhoc SqlParameter.

Example of an adhoc SqlParameter:

adapter.Parameters.Add("@WMSReceiptID", wmsReceiptID);

Example of a typed SqlParameter:

SqlParameter parameter = adapter.SelectCommand.Parameters.Add("@WMSReceiptID", SqlDbType.VarChar, 64);
      parameter.Value = wmsReceiptID;
      adapter.Parameters.Add(parameter);

When using an adhoc SqlParameter, the ADO.NET implementation grabs schema information. In this case, it led to SqlAdapter.Fill taking 20 seconds to execute. I switched in the typed SqlParameter and execution speed returned to normal.

The gory details

Today I tested a bug fix on a search screen. The business layer builds a dynamic query based upon the search criteria entered by the user. With shock, I noticed that it was taking 20 seconds to perform the search. The request was carried out across a VPN connection to the customer's network, but it had never taken 20 seconds to execute this query.

At first I thought it was a dormant problem with the SQL that finally decided to wake up. But when executed via SQL Query Analyzer, the query completed in 1 or 2 seconds.

To isolate the problem, I threw the code into a console application. The code uses a SqlDataAdapter to fill a DataTable. The particular instance of this query had one parameter that was filled via an ad hoc SqlParameter.

Following is a stripped down version of the test code...

SqlConnection connection = new SqlConnection(Database.ConnectionString);
      try 
      {
        connection.Open();
        SqlDataAdapter adapter = new SqlDataAdapter();
        adapter.SelectCommand =
          new SqlCommand("SELECT ...", connection);

        adapter.SelectCommand.Parameters.Add("@WMSReceiptID", "[SomeRecordID]");
        DataTable table = new DataTable();
        try
        {
          adapter.Fill(table);
        }
        catch (Exception E)
        {
          Console.WriteLine("Error: " + E.Message);
        }
      }
      finally 
      {
        connection.Close();
      }

The test program also took 20 seconds or so to execute the source code line "adapter.Fill(table);".  For kicks, I removed the SqlParameter and hardcoded the receipt ID. Bam! The call to adapter.Fill returned in 1 second.

Hmmm. Why would using a SqlParameter cause slow performance? I've used them hundreds, if not thousands of them, with no slowdown.

I downloaded a trial version of Automated QA's AQTime and profiled the test application. AQTime reported a large amount of time in UnsafeNativeMethods/Dbnetlib::ConnectionRead. I used the Call Graph to backtrack. Once I reached method SqlDataReader.get_MetaData. I reasoned that the adhoc SqlParameter was causing ADO.NET to fetch the schema information and doing so was taking a lot of time.

I switched to a typed SqlParameter and performance went back to its expected level.

Filed under  //

Comments [0]