当使用OracleDataReader读取数据时如何处理NULL值?

15

我正在开发我的第一个ASP.Net应用程序,在此过程中遇到了很多问题(主要背景是WinForms,最近有一个MVC5项目)。

我成功地使用OracleCommand建立了数据库连接并执行了查询,但是当我尝试读取行数据时,对于odr.GetDecimal(1)的第二行出现了Column contains NULL value。 有人知道如何处理在OracleDataReader中读取null值的情况吗?

以下是我的代码:

        List<YearsOfService> yearsOfService = new List<YearsOfService>();
        string SQL = "SELECT SCHOOL_YEAR as YEAR, " +
                            "TOTAL_SERVICE_CREDIT as ServiceCredited, " +
                            "RETIREMENT_SALARY as Salary, " +
                            "SOURCE_VALUE as CoveredEmployer " +
                     "FROM " + Schema + ".RANDOM_ORACLE_TABLE a " +
                     "WHERE MEMBER_ACCOUNT_ID = :memberAccountId";

        DbConnection dbc = new DbConnection();
        OracleCommand cmd = dbc.GetCommand(SQL);
        cmd.Parameters.Add(new OracleParameter("memberAccountId", memberAccountId));
        OracleDataReader odr = cmd.ExecuteReader();

        int counter = 0;
        if (odr.HasRows)
        {
            while (odr.Read())
            {
                YearsOfService yos = new YearsOfService();
                yos.Year = odr.GetInt16(0);
                yos.ServiceCredited = odr.GetDecimal(1); // Error on Second Pass

                yos.Salary = odr.GetDecimal(2);

                yos.CoveredEmployer = odr.GetString(3);

                yearsOfService.Add(yos);
                counter++;
            }
        }

        return yearsOfService;
    }

我原本认为对NULL值进行简单的检查,如果是NULL就用0替换(因为期望是Decimal类型的值),以下代码可以实现,但没有成功。出现了相同的错误:yos.ServiceCredited = Convert.IsDBNull(odr.GetDecimal(1)) ? 0 : odr.GetDecimal(1);

完整的错误信息如下:

'System.InvalidCastException'类型的异常在 Oracle.DataAccess.dll 中发生,但是未在用户代码中处理

附加信息: 列包含 NULL 数据

我已确认返回的两行数据格式如下:

Year|CreditedService|Salary  |CoveredEmployer
2013|0.70128        |34949.66|ER
2014|NULL           | 2213.99|NULL

有人能给出如何最好地继续的建议吗?当我浏览 OracleDataReader 时,如何处理接收到 NULL 值?


我没有使用过OracleDataReader,但是我猜你需要检查odr.GetValue(1)是否为空,而不是odr.GetDecimal(1) - juharr
另一个选择是在SQL中合并值。 - juharr
@DJKRAZE,不确定你的意思。不过我会查一下Coalesce。@juharr:我试过了,但是无论如何都会出现错误,因为yos.ServiceCredited需要一个Decimal值,而不仅仅是从GetValue()得到的object。@Syed:我尝试了那个方法,没有成功,还是同样的错误。 - Analytic Lunatic
哦,实际上我用SqlDataReader时很好用,所以我认为它也可以与OracleDataReader一起使用 :P - Syed Farjad Zia Zaidi
顺便提一下,你应该处理好你的连接和命令对象... - Syed Farjad Zia Zaidi
显示剩余2条评论
1个回答

35
yos.ServiceCredited = odr.IsDBNull(1) ? 0 : odr.GetDecimal(1);

OracleDataReader 提供了一个 IsDBNull() 方法。

而关于 GetDecimal() 的文档要求我们在调用该方法之前先调用 IsDBNull 来检查是否存在 null 值。

在调用此方法之前,请调用 IsDBNull 检查是否存在 null 值。


谢谢Abhi,这个方法很有用!我之前尝试使用了IsDBNull()方法,但是我实现得不正确。以前我尝试过类似于yos.ServiceCredited = Convert.IsDBNull(odr.GetDecimal(1))的东西。这是我第一次使用OracleDataReader,对它如何使用不同的Get()进行“列”引用还没有经验。感谢您的帮助! - Analytic Lunatic
4
谢谢你。还有其他人认为客户端必须在读取值之前进行预检查来确定该值是否为空绝对是一种疯狂的做法吗?为什么GetDecimal()等方法不像其他数据库驱动程序一样返回Null值呢?这似乎很荒谬。 - Black
1
@Black 我猜这就是我们使用 Oracle 的代价? - EKW
@Black 因为十进制值不能为 null。如果该方法能够返回你所描述的 null,那么你必须始终检查结果是否为 null,以便将其分配给 Decimal。 - Andy Hames
@AndyHames 他们应该像任何理智的人一样使用 default - EKW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接