2011-11-07 17 views
4

我正在尋找一些.net程序的代碼,我正在處理。該程序的前一作者在一年前向我提供了代碼。突然,我看到從代碼中拋出的異常,我沒有感動:關於空字符串和DBNull的困惑

if ((string)row["LevelName"] != "ABC") 

唯一的例外是「無法投類型的對象'System.DBNull爲鍵入‘System.String’

我認爲字符串是一個可空數據類型,所以我怎麼可能會得到這個異常

+0

此代碼已運行良好超過一年;我覺得我一定在某個地方弄錯了什麼 –

+0

是的,事實上,我做到了。有問題的代碼沒有準備好DBNull值,因爲它永遠不會出現在我正在運行的特定查詢中。我在修改查詢時犯了一個錯誤,因此錯誤出現了。 –

+0

感謝您提供豐富的答案,每個人。我把它們都投了票。難怪我讀的SQL書叫NULL「四個字母的單詞」。 –

回答

7

DBNull是它自己的類,它包含itsself在一個名爲Value屬性singleton實例。 DBNull.Value不等於null,因爲它是對此類的實例的引用。

如果沒有值,大多數(即使不是全部)數據庫包裝將返回DBNull.Value而不是null。其中一個原因是因爲返回一個真實的null可能意味着根本不存在任何行,而不僅僅是列中的空值(這取決於您使用哪些對象來獲取值)。

通常,as運算符對於DBNull非常有用,可以與任何可空類型(包括string)一起使用。

string str = reader["Name"] as string; 
int? i = reader["Age"] as int?; 

這也可能是值得一提的是,??運營商是非常有用的也在這裏,當你需要一個非空值類型(雖然它不看太漂亮)。

int i = reader["Age"] as int? ?? -1; 

我發現這很方便,因爲它是LINQ select子句中的一件小事。

+0

我很害怕我的快速手指。幸運的是,我在離開該評論前2分鐘對該帖子進行了編輯,以便它**具有正確的示例。對於那個很抱歉。 – Connell

+0

沒問題,我刪除了我的評論和+1。 – Rob

9

我相信你要找的是什麼?

if ((row["LevelName"] as String) != "ABC") 

沒有隱式轉換DBNull和String之間。

它可能以前工作過,因爲剛好在您的數據庫中該列中沒有NULL。也許有些數據被破壞,或者有人在表上改變了NOT NULL約束。

基本上,如果您明確施放了某些東西,最好確保它們具有兼容的動態類型,否則會拋出異常。 as操作員基本上說「如果可能的話將其轉換爲此值,否則邏輯值爲空。」顯然,as運算符只能用於引用類型,因爲結構不能爲空。

+2

你的答案暗示了這一點,但值得說明的是:在使用顯式類型轉換'(Type)變量'會導致'InvalidCastException'的情況下,使用'variable as Type'將產生'null'。 – Rob

2

.NET nullDBNull.Value之間存在差異。在這裏,您可以看到類DBNull和該類的Value字段。

你應該能夠做這樣的事情:

if (row["LevelName"].Value == DBNull.Value) 
    return false; 
else if (row["LevelName"].ToString() != "ABC") 
    // do something 
    // .... 
3

DBNull表示數據庫中的空值。這與.NET null不同,它表示一個空引用。

代碼突然失敗,因爲有人更改或插入了空白的記錄。

是的,字符串可以爲空,但是您將一個dbnull投射到字符串。您必須檢查dbnull,如果它存在,則將其替換爲null。

4

DBNull表示在給定的數據庫列中沒有數據。如果在數據庫中創建新記錄,但沒有將值分配給「LevelName」列,則會發生這種情況。

DBNull與空對象引用或空字符串變量不同。 DBNull表示列數據從未設置。如果您爲「LevelName」列指定一個空值,那麼該列已經初始化並且它將返回null(而不是DBNull)。