是否可以从故障点开始继续运行代码
本文关键字:开始 继续 运行 代码 故障 是否 | 更新日期: 2023-09-27 18:29:58
好的,我有一些非常简单的代码,我将在下面发布。从本质上讲,我有一个到数据库的连接,我想将查询中的列的子集映射到一个特定的类。问题是这些可能为空。
我想知道,如果在某一行引发异常,我们是否可以从下一行恢复整个块。
因此,如果执行下面的代码,并且第6行出现错误。有没有一种优雅的方法可以捕获异常并使代码在第7行继续运行。从本质上讲,这就好像第6行从未执行过一样。
private static Column MapTableToColumn(OracleDataReader reader){
Column c = new Column();
c.ColumnName = Convert.ToString(reader["COLUMN_NAME"]);
c.DataType = Convert.ToString(reader["DATA_TYPE"]);
c.DataLength = Convert.ToInt32(reader["DATA_LENGTH"]);
c.DataPrecision = Convert.ToInt32(reader["Data_Precision"]);//<---Line 6
c.DataScale = Convert.ToInt32(reader["Data_scale"]);//<--- Line 7
c.AllowDBNull = Convert.ToBoolean(reader["ALLOW_DB_NULL"]);
c.IsReadOnly = Convert.ToBoolean(reader["IS_READ_ONLY"]);
c.IsLong = Convert.ToBoolean(reader["IS_LONG"]);
c.IsKey = Convert.ToBoolean(reader["IS_KEY"]);
c.KeyType = Convert.ToString(reader["KEY_TYPE"]);
c.IsUnique = Convert.ToBoolean(reader["IS_UNIQUE"]);
c.Description = Convert.ToString(reader["DESCRIPTION"]);
return c;
}
需要注意的是,我并不是在要求最佳实践,这不是我打算在实际代码中使用的东西(除非它绝对是天才)。我只是想知道这是否可能,如果可能的话,人们会怎么做。
我的研究
我的大部分研究都是主动的,而不是被动的。我想知道在读取给定字段之前,它是否可能为null。如果是,那么我会进行检查以确定字段是否为null,然后将其设置为默认值。它基本上避免了发生错误的可能性,我认为这是一个非常好的解决方案。我只是想尝试一下,因为我知道当抛出异常时,最内部的异常包含抛出它的行号。基于此,如果您将异常放入引发异常的类中,则假设您应该能够使用反射,以便从其最后一点开始继续运行。我只是不确定你会怎么做。我还考虑过在每一条线上进行尝试接球的可能性,我认为这会非常有效;然而,我认为这将是非常丑陋的。
不,您所要求的在C#中是不可能的。
相反,这个问题的正确解决方案是使用更好的解析方法,这些方法一开始就不会抛出异常。如果您的输入值可以为null,那么请使用可以接受null值的解析方法。
您可能需要做的第一件事是为int/bool字段使用可为null的类型,这样您就可以支持null值。接下来,您需要创建自己的方法来解析int/boll。如果您的输入为null,则返回null;如果不是,则使用int.TryParse
、bool.TryParse
(如果输入的类型正确,则分别使用as
,仅强制转换为object
)。
然后,通过使用这些方法,而不是Convert
,您将不会首先抛出异常(即使它可以工作,也不应该在这里这样做,因为异常是针对异常情况的,而不是预期的控制流)。
如果异常是预期的,则它不是异常从不捕获空引用异常空引用异常是一个错误。相反,编写代码以避免该错误。
您可以轻松地编写测试null的辅助方法,或者使用像Int32.TryParse
这样的方法来处理格式错误的字符串。
检查IsDBNull
SqlDataReader.IsDBNull方法
Reader对每个SQL数据类型都有方法
例如
SqlDataReader.GetSqlBoolean
如果数据在SQL中是字符串(char,nchar),则首先检查null,然后TryParse
例如
DateTime.TryParse
顺序位置更快
这是可为null的Int16 的示例
Int16? ID;
ID = rdr.IsDBNull(4) ? (Int16?)null : rdr.GetInt16(4);
如果你想要一个默认的
Int16 ID;
ID = rdr.IsDBNull(4) ? 0 : rdr.GetInt16(4);
您需要对每个变量赋值进行try/catch,并且在尝试之前需要初始化所有Column
实例值。这将相对缓慢。
至于基于行号的反射:我不会依赖行号,因为对代码进行一个简单、无辜的更改就会完全放弃它。
我会专门检查null。如果你期待它们,你几乎不能称它们为"例外"。这样做的方法是reader.IsDBNull
。它采用列索引(而不是列名),因此您需要使用reader.GetOrdinal
:解析索引
if (reader.IsDBNull(reader.GetOrdinal("Data_Precision"))) {
// It's null
} else {
// It's not null
}