1

Resolved

ReliableSqlConnection.ExecuteCommand<T> makes wrong assumptions about return type

description

Note: this bug concern Azure Integration Pack, more precisely Transient Exception Handling.

ExecuteCommand<T> is the only method available to execute NonQuery, Scalar and Reader.

In my case, we need to use the generic ExecuteScalar with object result, then cast the result in the correct type.

If you use ExecuteCommand<object>(), you will see that a IDataReader is returned instead of an object.

In ReliableSqlConnection.cs, the IsAssignable() method is wrongly used : it's used as <type>.IsAssignableFrom(<base>) instead of <base>.IsAssignableFrom(<type>)

Exemple :

typeof(SqlDataReader).IsAssignableFrom(typeof(IDataReader)) returns false
typeof(IDataReader).IsAssignableFrom(typeof(SqlDataReader)) returns true

So, if (resultType.IsAssignableFrom(typeof(IDataReader))) returns always true for objects, and always false for SqlDataReader.

It works for most case, because I suppose all tests were written with ExecuteCommand<IDataReader> (which works in both cases).

It's the same for XmlReader.

To fix this, what you only need is to reverse the test.

Bonus remark : did you really test the code against ExecuteScalar with DBNull result ? I suppose no, because ReliableSqlConnection change the behavior of IDbCommand.ExecuteScalar when null value is returned.

comments

styx31 wrote Apr 26, 2013 at 9:52 AM

This bug is still present in EntLib6.

styx31 wrote Apr 26, 2013 at 10:24 AM

Two simple units tests to add to Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.Tests.ReliableSqlConnectionTest which fails :
[TestMethod]
public void TestExecuteSimpleCommandWithObjectResult()
{
    SqlCommand command = new SqlCommand("SELECT cast(1 as int)");
    object result = connection.ExecuteCommand<object>(command);

    Assert.IsNotNull(result, "Unexpected null result");

    Type resultType = result.GetType();

    Assert.AreEqual(typeof(int), resultType, "Unexpected result type");
    Assert.AreEqual(1, Convert.ToInt32(result), "Unexpected result");
}

[TestMethod]
public void TextExecuteSelectCommandToGetSqlDataReader()
{
    SqlCommand command = new SqlCommand("SELECT [ProductCategoryID], [Name] FROM [SalesLT].[ProductCategory]");
    using (SqlDataReader reader = connection.ExecuteCommand<SqlDataReader>(command))
    {
        while (reader.Read())
        {
            int id = reader.GetInt32(0);
            string name = reader.GetString(1);

            Trace.WriteLine(string.Format("{0}: {1}", id, name));
        }

        reader.Close();
    }
}

gmelnik wrote May 25, 2013 at 3:00 PM