C#找出导致Sql异常的列

时间:2010-05-12 08:33:05

标签: c# database exception invalidoperationexception

我从SQL数据读取器(MS SQL作为数据存储区)中获取异常,并且我想知道哪个列名会导致抛出此异常。但我无法在InnerException中找到它..无处。

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

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

请将它隐藏在哪里?

1 个答案:

答案 0 :(得分:2)

你做不到。数据读取器不会在其堆栈跟踪中进行通信。你可以做的是将数据阅读器的使用包装在另一个类中。在我正在研究的项目中,我们使用了扩展方法。该课程如下:

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转换。