SqlDataReader返回空值而不是null值,对于一个int字段。

6
我正在使用SqlDataReader从SQL Server 2012数据库中获取数据。
SqlConnection connection = (SqlConnection)_db.Database.GetDbConnection();
await connection.OpenAsync();
SqlCommand command = new SqlCommand("dbo.[sp_MyStoredPrc] @InputId=1", connection);
var reader = await command.ExecuteReaderAsync();

if (reader.HasRows)
{
    while (reader.Read())
    {
        int? var1 = (int?)reader["Column1Name"];
    }
}

当从数据库读取一个空的int字段时,reader["Column1Name"]为空,因此代码在运行时会抛出InvalidCastException异常。

我已经尝试过:

reader.GetInt32(reader.GetOrdinal("Column1Name"))

但是这会抛出 System.Data.SqlTypes.SqlNullValueException 异常。

我也尝试过

reader.GetSqlInt32(reader.GetOrdinal("Column1Name"))

这段代码返回了 null,但返回类型是 SqlInt32 而不是我所期望的 int?

最终我采用了以下方法:

if (!reader.IsDBNull(reader.GetOrdinal("Column1Name"))) 
    int? var1 = (int?)reader["Column1Name"];

运行正常。

问题:

  1. 难道没有比调用IsDBNull方法更简单的方法吗?

  2. 如果数据库值为NULL且字段为int类型,为什么reader["Column1Name"]返回空白而不是null


我不确定,但尝试使用 Convert.ToInt32(reader["Column1Name"]); - SergeyAn
我收到一个异常,因为Reader ["Column1Name"]为空。 - dfmetro
你确定 db 值是 null 吗?它可能为空,但并不意味着它是 null。否则,处理它的唯一方法就是检查空值。 - SergeyAn
我确定它是空的,我可以使用SQL分析器跟踪来查看它是否返回了null。此外,reader.GetSqlInt32(reader.GetOrdinal("Column1Name")) 返回null。 - dfmetro
谢谢澄清。此外,Column1Name和ColumnName1是不同的字段吗? - SergeyAn
这是一个好问题!另一方面,我个人使用答案中描述的方法。它展示了如何将从reader返回的通用信息读取到List<dynamic>中。同样的方式可以将结果保存在List<Dictionary<string, object>>中。作为结果,可以读取数据,而且读取时不会有读取null的问题,因为您是通过序号读取数据。 - Oleg
2个回答

5
为什么如果数据库值为NULL且字段是int类型,reader["Column1Name"]返回空白而不是null?
实际上,如果数据库值为NULL,reader["Column1Name"]返回DBNull.Value。(在Visual Studio调试器中,该值似乎为空白,因为DBNull.ToString()返回一个空字符串。)您无法使用强制转换运算符将DBNull.Value直接转换为int?
难道没有比调用IsDBNull方法更简单的方法吗?
是的,使用as运算符而不是强制转换:
int? var1 = reader["Column1Name"] as int?;

因为DBNull.Value不是一个int类型,所以as运算符返回null


0

C#无法将字符串转换为int?使用(int?)。最安全的方法是使用条件运算符检查null,然后手动将值设置为null。

//Get the column index to prevent calling GetOrdinal twice
int COLUMNNAME1 = reader.GetOrdinal("ColumnName1");

while (reader.Read())
{
    int? var1 = reader.IsDBNull(COLUMNNAME1) ? null : reader.GetInt32(COLUMNNAME1);
}

同样地,如果您有非空数据类型,可以检查它们是否为空并将它们设置为默认值。
int STRINGCOLUMN = reader.GetOrdinal("StringColumn");
int INTCOLUMN = reader.GetOrdinal("IntColumn");
int DATECOLUMN = reader.GetOrdinal("DateColumn");
int BOOLCOLUMN = reader.GetOrdinal("BoolColumn");

while (reader.Read())
{
    string var1 = reader.IsDBNull(STRINGCOLUMN) ? "" : reader.GetString(STRINGCOLUMN);
    int var2 = reader.IsDBNull(INTCOLUMN) ? 0 : reader.GetInt32(INTCOLUMN);
    DateTime var3 = reader.IsDBNull(DATECOLUMN) ? DateTime.MinValue : reader.GetDateTime(DATECOLUMN);
    bool var4 = reader.IsDBNull(BOOLCOLUMN) ? false : reader.GetBoolean(BOOLCOLUMN);
}

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