首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ADO.NET 讀取資料庫 NULL 值正確判斷技巧:DBNull.Value 與 Convert.IsDBNull

     編輯:ASP.NET 基礎

前言

在 ADO.NET 使用 SqlDataReader 讀取資料庫欄位時,資料庫的 NULL 值在 .NET 中對應的是 System.DBNull,而非 C# 的 null。這是初學者最常踩的坑,直接導致空值判斷失效。本文詳細說明正確判斷方式與避坑指南。

一、錯誤示範:為什麼 dr["Name"] == null 失效?

// 錯誤寫法
while (dr.Read())
{
    string name = dr["Name"].ToString(); // 若為 DBNull 會拋出例外
    if (dr["Name"] == null)  // 永遠為 false!
    {
        number += 1;
    }
}

根因分析:

  • 資料庫 NULL → .NET 為 DBNull.Value(單例物件)
  • dr["Name"] 回傳 object,實際型別為 object {System.DBNull}
  • DBNull.Value != null,故 == null 永遠不成立
  • 呼叫 ToString() 會拋出 InvalidCastException

二、正確判斷三種寫法

方法 1:比對 DBNull.Value(最直觀)

if (dr["Name"] == DBNull.Value)
{
    number += 1;
}

方法 2:使用 Convert.IsDBNull(推薦,語意清晰)

if (Convert.IsDBNull(dr["Name"]))
{
    number += 1;
}

方法 3:搭配安全取值模式(實務最常用)

// 取得字串,若為 NULL 則回傳 string.Empty
string name = dr["Name"] == DBNull.Value ? "" : dr["Name"].ToString();

// 或使用擴充方法
public static string GetStringSafe(this IDataRecord dr, string columnName)
{
    int ordinal = dr.GetOrdinal(columnName);
    return dr.IsDBNull(ordinal) ? "" : dr.GetString(ordinal);
}

// 使用
string name = dr.GetStringSafe("Name");

三、完整修正範例

int nullCount = 0;
string connStr = @"Data Source=.\SQLEXPRESS;Initial Catalog=TestDB;Integrated Security=True";

using (var conn = new SqlConnection(connStr))
{
    conn.Open();
    using (var cmd = new SqlCommand("SELECT Name, InputDate FROM TestTable", conn))
    using (var dr = cmd.ExecuteReader())
    {
        while (dr.Read())
        {
            // 正確判斷 NULL
            if (Convert.IsDBNull(dr["Name"]))
            {
                nullCount++;
                continue;
            }

            // 安全取值
            string name = dr["Name"].ToString();
            DateTime inputDate = dr.GetDateTime(dr.GetOrdinal("InputDate"));
            
            Console.WriteLine($"Name: {name}, Date: {inputDate:yyyy-MM-dd}");
        }
    }
}

Console.WriteLine($"Name 為 NULL 的筆數:{nullCount}");

四、資料型別對應表

SQL 型別.NET 型別NULL 表示安全讀取方法
varchar/nvarcharstringDBNull.Valuedr.IsDBNull(i) ? "" : dr.GetString(i)
int/bigintint/longDBNull.Valuedr.IsDBNull(i) ? 0 : dr.GetInt32(i)
datetime/dateDateTimeDBNull.Valuedr.IsDBNull(i) ? DateTime.MinValue : dr.GetDateTime(i)
decimal/moneydecimalDBNull.Valuedr.IsDBNull(i) ? 0m : dr.GetDecimal(i)
bitboolDBNull.Valuedr.IsDBNull(i) ? false : dr.GetBoolean(i)

五、進階:Nullable 型別對應

// 使用 Nullable 型別直接對應資料庫 NULL
int? age = dr.IsDBNull(dr.GetOrdinal("Age")) ? (int?)null : dr.GetInt32(dr.GetOrdinal("Age"));
DateTime? birthDate = dr.IsDBNull(dr.GetOrdinal("BirthDate")) ? (DateTime?)null : dr.GetDateTime(dr.GetOrdinal("BirthDate"));

// C# 7.0+ 模式比對
if (dr["Age"] is int ageValue) { /* 非 NULL */ }
if (dr["Age"] is DBNull) { /* 是 NULL */ }

六、常見錯誤情境與對策

錯誤情境錯誤結果正確做法
dr["Col"].ToString() 未判斷 NULLInvalidCastException先判斷 Convert.IsDBNull(dr["Col"])
dr.GetInt32(i) 讀取 NULL 欄位SqlNullValueException先判斷 dr.IsDBNull(i)
dr["Col"] == null 判斷永遠 false,邏輯錯誤改用 dr["Col"] == DBNull.Value
DataTable.Select 篩選 NULL語法錯誤使用 "Col IS NULL" 或 "Col IS NOT NULL"

結語

資料庫 NULL ≠ C# null,這是 ADO.NET 開發的鐵律。養成「先 IsDBNull 判斷,再安全取值」的習慣,並善用 Convert.IsDBNull、DataRecordExtensions.GetFieldValue<T> 或自訂擴充方法,能徹底避免空值相關的執行期例外與邏輯錯誤。記住:DBNull.Value 是單例物件,代表「資料庫層面的無值」,而 null 代表「.NET 參考型別的無物件」,兩者語意層級完全不同。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved