在转换 C# 之前检查 DbNull

Check DbNull before casting C#

我正在尝试查询 SQL 服务器数据库和 return JSON 中的响应。我正在尝试下面的代码

      using (SqlConnection connection = new SqlConnection(connStr))
        {
            SqlCommand command = new SqlCommand(commandText, connection);
            command.Parameters.Add("@ROOM_Data", SqlDbType.VarChar);
            command.Parameters["@ROOM_Data"].Value = ROOM;
            connection.Open();
            List<DatabaseResult> records = new List<DatabaseResult>();

            using (var reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    var row = new DatabaseResult
                    {
                        request_id = (int)reader["request_id"],
                        room = (string)reader["room"],
                        jrs_no = (int)reader["jrs_no"],
                        submit_date = (DateTime)reader["submit_date"],
                        sample_no = (int)reader["sample_no"],
                        animal_id = (string)reader["animal_id"],
                        pen_id = (string)reader["pen_id"],
                        ped_no = (string)reader["ped_no"],
                        gender = (string)reader["gender"],
                        dob = (DateTime)reader["dob"],
                        parent_mating = (string)reader["parent_mating"],
                        generation = (string)reader["generation"],
                        allele = (string)reader["allele"],
                        status_type = (string)reader["status_type"],
                        genotype = (string)reader["genotype"],
                        comments = (string)reader["comments"],
                        completion_date = (DateTime)reader["completion_date"],
                        disposition = (string)reader["disposition"],

                    };
                    records.Add(row);
                }
                return Ok(records);

当任何字段中有空值时,我会遇到问题。我试着查看其他论坛,我是否理解我们需要在投射之前检查每一列是否为空。但是我正在检查我是否可以通过可以处理所有情况的方法来做?

一个问题是 int 在转换时不处理空值。

尝试

sample_no = (int?)reader["sample_no"]

在你的 class DatabaseResult

声明 sample_noint? sample_no

int? 表示它的可为空的 int,如果您将空值传递给它,它不会抛出异常。

另一种方法是 int.TryParse 如果它检测到它是空值,它将放置 0。

如果您必须使用数据读取器并且您正在定义自己的原始 sql,这似乎是这种情况,那么在 sql 中您可以包装修改您的 sql在 select 部分使用 ISNULL 检查的语句。 例如 - 确保字符串列 returns 和空字符串 ('') 而不是 NULL

select isnull(foo,'') from myTable

这样试试

public static class SqlReaderExtention {

     public static T GetValue<T>(this SqlDataReader reader, string fieldName) {
        int columnIndex = reader.GetOrdinal(fieldName);
        if (reader.IsDBNull(columnIndex)) {
           return default(T);
        }

        return (T)reader.GetValue(columnIndex);
     }
 }
request_id = reader["request_id"] == DBNull.Value ? null : (int?)reader["request_id"] ,
room = reader["room"].ToString(),
jrs_no = reader["jrs_no"] == DBNull.Value ? null : (int?)reader["jrs_no"] ,
submit_date = reader["submit_date"] == DBNull.Value ? null : (DateTime?)reader["submit_date"],
sample_no = reader["sample_no"] == DBNull.Value ? null : (int?)reader["sample_no"],
animal_id = reader["animal_id"].ToString(),
pen_id = reader["pen_id"].ToString(),
ped_no = reader["ped_no"].ToString(),
gender = reader["gender"].ToString(),
dob = reader["dob"] == DBNull.Value ? null : (DateTime?)reader["dob"],
parent_mating = reader["parent_mating"].ToString(),
generation = reader["generation"].ToString(),
allele = reader["allele"].ToString(),
status_type = reader["status_type"].ToString(),
genotype = reader["genotype"].ToString(),
comments = reader["comments"].ToString(),
completion_date = reader["completion_date"] == DBNull.Value ? null : (DateTime?)reader["completion_date"],
disposition = reader["disposition"].ToString(),

数据库空值你可以随意管理。 int 和 datetime 变量更改为 int?和日期时间?分别或者您可以设置默认值以防 db value null

您可以像这样对照 DBNull.Value 检查列值:

request_id = (reader["request_id"] == DBNull.Value) ? default(int) : (int)reader["request_id"];

如果您想简化所有列的过程,请创建一个扩展方法来与 DBNull.Value 进行比较,如下例所示:

// using DBNull.Value comparison
public static T GetValue<T>(this SqlDataReader reader, string columnName)
{
    var value = reader[columnName]; // read column value

    return value == DBNull.Value ? default(T) : (T)value;
}

// alternative using GetOrdinal and IsDBNull
public static T GetValue<T>(this SqlDataReader reader, string columnName) 
{
    int index = reader.GetOrdinal(columnName); // read column index

    return reader.IsDBNull(index) ? default(T) : (T)reader.GetValue(index);
}

用法示例:

request_id = GetValue<int>(reader, "request_id");

您必须小心地将 int 解析为您的代码,因为它可能 return 您出错。

为什么不先尝试 运行 代码隐藏并使用 isnull.

在您的查询中修复它

select isnull(yourNumField,'0')

虽然我同意针对一般用法提到的扩展方法选项,但如果您只需要针对 DB Null 快速检查一个可能为 null 的值,我会推荐这样的方法:

if (rdr["request_id"] != DBNull.Value)
   RequestID = Convert.ToInt32(rdr["request_id"]);

或者,你可以更简洁,并提供一个默认值:

RequestID = (rdr["request_id"] != DBNull.Value) ? Convert.ToInt32(rdr["request_id"]) : 0;