Few weeks ago I wrote about an ugly backward compatibility break in Microsoft SQL Server 2008. So how to write a clean code which works correctly on both 2005 and 2008 and deals with the sp_helpuser issue described in my previous post?
Let's assume that the original code is as follows:
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "sp_helpuser";
conn.Open();
SqlDataReader r = cmd.ExecuteReader();
while ( r.Read() )
{
// throws an exception on SQL Server 2008
// since GroupName has been renamed to RoleName
if ( (string)r["GroupName"] ) == "anyvalue" )
...
}
The subtle side issue here is that it's not easy to determine whether a column is or is not available in SqlDataReader. You can try to read a value and catch an exception but this is just slow. However, another, not-so-obvious method has been proposed - please take a look here.
Let's just then add two auxiliary methods:
private bool columnExists( SqlDataReader reader, string columnName )
{
reader.GetSchemaTable().DefaultView.RowFilter = "ColumnName= '" + columnName + "'";
return (reader.GetSchemaTable().DefaultView.Count > 0);
}
private string GetGroupRoleName( SqlDataReader reader )
{
if ( columnExists( reader, "GroupName" ) )
return (string)reader["GroupName"];
if ( columnExists( reader, "RoleName" ) )
return (string)reader["RoleName"];
/* return something unique */
return Guid.NewGuid().ToString();
}
and change the original code to:
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "sp_helpuser";
conn.Open();
SqlDataReader r = cmd.ExecuteReader();
while ( r.Read() )
{
// no exception, works on both 2005 and 2008
if ( GetGroupRoleName( r ) == "anyvalue" )
...
}
No comments:
Post a Comment