C # Узнайте, какой столбец вызвал исключение Sql - PullRequest
2 голосов
/ 12 мая 2010

Я получаю исключение от SQL Data Reader (MS SQL как хранилище данных), и я хотел бы знать, какое имя столбца вызывает это исключение.Но я не могу найти его в InnerException ... нигде.

((System.InvalidOperationException)ex.InnerException).StackTrace:

System.Data.SqlClient.SqlDataReader.ReadColumnHeader(Int32 i)
System.Data.SqlClient.SqlDataReader.IsDBNull(Int32 i)
...

Где это спрятано, пожалуйста?

1 Ответ

2 голосов
/ 12 мая 2010

Вы не можете. Считыватель данных не сообщает об этом в своей трассировке стека. Что вы можете сделать, это обернуть использование чтения данных в другом классе. В проекте, над которым я работаю, мы использовали для этого методы расширения. Класс выглядит так:

public static class DataRecordExtensions
{
    public static byte GetByte(this IDataRecord record, string name)
    {
        return Get<byte>(record, name);
    }

    public static short GetInt16(this IDataRecord record, string name)
    {
        return Get<short>(record, name);
    }

    public static int GetInt32(this IDataRecord record, string name)
    {
        return Get<int>(record, name);
    }

    private static T Get<T>(IDataRecord record, string name)
    {
        // When the column was not found, an IndexOutOfRangeException will be 
        // thrown. The message will contain the name argument.
        object value = record[name];

        try
        {
            return (T)value;
        }
        catch (InvalidCastException ex)
        {
            throw BuildMoreExpressiveException<T>(record, name, value, ex);
        }
    }

    private static InvalidCastException BuildMoreExpressiveException<T>(
        IDataRecord record, string name, 
        object value, InvalidCastException ex)
    {
        string exceptionMessage = string.Format(CultureInfo.InvariantCulture,
            "Could not cast from {0} to {1}. Column name '{2}' of {3} " + 
            "could not be cast. {4}",
            value == null ? "<null>" : value.GetType().Name, 
            typeof(T).Name, name, record.GetType().FullName, ex.Message);

        return new InvalidCastException(exceptionMessage, ex);
    }
}

Вы можете использовать его следующим образом:

using (var reader = SqlHelper.ExecuteReader(...))
{
    while (reader.Read())
    {
        yield return new Order()
        {
            OrderId = reader.GetInt32("orderId"),
            ItemId = reader.GetInt32("itemId")
        };
    }
}

кстати. Такой класс также позволяет вам вернуть Nullable<T> объекты и избавиться от тех ручных DbNull преобразований, которые вам еще нужно сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...