C# 找出导致 Sql 异常的列

发布于 2024-09-01 13:34:28 字数 312 浏览 2 评论 0原文

我从 SQL 数据读取器(MS SQL 作为数据存储)收到异常,我想知道哪个列名导致抛出此异常。但我在 InnerException.. 中找不到它。

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

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

请问它藏在哪里?

I'm getting an exception from SQL Data Reader (MS SQL as datastore) and I'd like to know which column name causes this Exception to be thrown. But I cannot find it in the InnerException.. nowhere.

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

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

Where is it hidden please ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我不在是我 2024-09-08 13:34:28

你不能。数据读取器不会在其堆栈跟踪中传达该信息。您可以做的是将数据读取器的使用包装在另一个类中。在我正在进行的一个项目中,我们为此使用了扩展方法。该类如下所示:

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 对象,并摆脱那些您需要执行的手动 DbNull 转换。

You can't. The data reader does not communicate that in its stack trace. What you can do is wrapping the use of the data reader in another class. In a project I'm working on we used extension methods for this. The class looks like this:

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);
    }
}

You can use it as follows:

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

btw. Such an class also allows you to get Nullable<T> objects back and get rid of those manual DbNull conversions you else need to do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文