Apa perbedaan antara Null dan System.DBNull.Value?

92

Apakah ada perbedaan antara null dan System.DBNull.Value? Jika ya, apa itu?

Saya memperhatikan perilaku ini sekarang -

while (rdr.Read())
{
    if (rdr["Id"] != null) //if (rdr["Id"] != System.DBNull.Value)  
    {
        int x = Convert.ToInt32(rdr["Id"]);
    }
}

Sementara saya mengambil data dari database menggunakan datareader sql, meskipun tidak ada nilai yang if(rdr["Id"] != null)dikembalikan truedan akhirnya melemparkan pengecualian untuk memberikan null sebagai integer.

Tapi, ini jika saya menggunakan if (rdr["Id"] != System.DBNull.Value)pengembalian false.

Apa perbedaan antara null dan System.DBNull.Value?

pavanred
sumber
Yah, mereka tidak berhubungan. Salah satunya adalah instance statis kelas di System.Data, dan yang lainnya adalah nilai khusus yang menandakan kurangnya referensi. Mereka tidak ada hubungannya satu sama lain. Bisakah Anda menjelaskan apa yang membuat Anda bingung? Apakah pertanyaan Anda yang sebenarnya "mengapa melakukan DataRowsdan DataReadersmenempatkan DBNull.Valuediri mereka sendiri, bukan null?"
mqp
Yah, itu bukan awalnya, tetapi setelah belajar dari apa yang Anda katakan, saya penasaran. Bisakah Anda memberi tahu saya mengapa DataRows dan DataReaders menempatkan DBNull.Value dalam dirinya sendiri, bukan null?
pavanred
Saya sendiri tidak yakin. Berikut satu jawabannya: stackoverflow.com/questions/4488727/what-is-the-point-of-dbnull/… Mungkin juga sebelum tipe nilai nullable ada di C #, akan lebih merepotkan untuk ditangani null.
mqp
1
Saya punya jawaban di sini, tapi saya menyadari itu lebih cocok untuk stackoverflow.com/questions/4488727/what-is-the-point-of-dbnull - jadi saya memindahkannya
Marc Gravell

Jawaban:

118

Yah, nullbukan contoh jenis apa pun. Sebaliknya, ini adalah referensi yang tidak valid.

Namun, System.DbNull.Valueadalah referensi yang valid ke instance System.DbNull( System.DbNulladalah singleton dan System.DbNull.Valuememberi Anda referensi ke instance tunggal dari kelas itu) yang mewakili nilai yang tidak ada * dalam database.

* Biasanya kami akan mengatakannya null, tetapi saya tidak ingin mengacaukan masalahnya.

Jadi, ada perbedaan konseptual yang besar di antara keduanya. Kata kunci nullmewakili referensi yang tidak valid. Kelas System.DbNullmewakili nilai yang tidak ada dalam bidang database. Secara umum, kita harus mencoba menghindari penggunaan hal yang sama (dalam kasus ini null) untuk merepresentasikan dua konsep yang sangat berbeda (dalam hal ini referensi yang tidak valid versus nilai yang tidak ada dalam field database).

Perlu diingat, inilah mengapa banyak orang menganjurkan menggunakan pola objek nol secara umum, yang merupakan System.DbNullcontoh.

jason
sumber
43
+1 Contoh praktis: jika Anda menggunakan IDbCommand.ExecuteScalar(), dapat mengembalikan null (tidak ada catatan yang dikembalikan) atau DbNull(kolom pertama dalam catatan pertama adalah 'nilai yang tidak ada'). Tanpanya DbNullAnda tidak akan bisa membedakan yang satu dari yang lain.
C.Evenhuis
Saya sangat menyarankan untuk menggunakan bahasa yang melarang penggunaan Null, dan melakukannya dengan biaya tambahan 0. hidup ini terlalu pendek untuk "pola objek nol"
nicolas
3
Referensi nol benar-benar valid. ☺
IllidanS4 mendukung Monica
@ C.Evenhuis Nah, ada saran umum lainnya: fungsi harus mengembalikan hanya satu jenis nilai. Itulah mengapa orang lebih suka kode TypeScript yang diketik dengan baik. "Apa status eksekusi" berbeda dari "Apa hasil komputasi". Yaitu. mereka bisa saja memutuskan untuk mengimplementasikan fungsi ini dengan cara lain (mungkin parameter out, atau objek yang mirip dengan objek respon permintaan HTTP). Tentu, ini adalah komplikasi yang sebenarnya tidak diinginkan, tetapi jika mereka telah melakukannya, mungkin null dapat digunakan sebagai pengganti DbNull.
klenium
21

Dari dokumentasi kelas DBNull :

Jangan bingung dengan pengertian null dalam bahasa pemrograman berorientasi objek dengan objek DBNull. Dalam bahasa pemrograman berorientasi objek, null berarti tidak adanya referensi ke suatu objek. DBNull mewakili varian yang tidak diinisialisasi atau kolom database yang tidak ada.

Heinzi
sumber
11

DBNull.Value menjengkelkan untuk ditangani.

Saya menggunakan metode statis yang memeriksa apakah itu DBNull dan kemudian mengembalikan nilainya.

SqlDataReader r = ...;
String firstName = getString(r[COL_Firstname]);

private static String getString(Object o) {
   if (o == DBNull.Value) return null;
   return (String) o;
}

Selain itu, ketika memasukkan nilai ke dalam DataRow, Anda tidak dapat menggunakan "null", Anda harus menggunakan DBNull.Value.

Memiliki dua representasi "nol" adalah desain yang buruk tanpa manfaat yang jelas.

Kebencian
sumber
2
Sentimen jijik yang kami bagikan tentang: pernyataan terakhir Anda hanya dibuat-buat oleh ironi karena muncul di sini untuk membaca ini dan mengetahui nama pengguna Anda "
menjijikkan
5

DBNull.Value adalah apa yang dikembalikan penyedia .NET Database untuk mewakili entri null dalam database. DBNull.Value bukan null dan perbandingan dengan null untuk nilai kolom yang diambil dari baris database tidak akan berfungsi, Anda harus selalu membandingkan dengan DBNull.Value.

http://msdn.microsoft.com/en-us/library/system.dbnull.value.aspx

James Michael Hare
sumber
ps Anda juga harus menggunakan DBNull.Value untuk meneruskan parameter null ke database, jika tidak, parameter tersebut dapat diinterpretasikan sebagai tidak dilewatkan.
James Michael Hare
1
DBNull bukanlah "apa yang dikembalikan database" - ini hanyalah bagaimana ADO.NET memilih untuk menafsirkannya; Secara pribadi saya tidak yakin bahwa interpretasi ini sangat berharga
Marc Gravell
@MarcGravell Ya, Marc, Anda benar. Aku salah mengucapkannya. ASP.NET menerjemahkan nilai kolom null database ke DBNull. Nilai
James Michael Hare
3

DataRow memiliki metode yang disebut IsNull()yang dapat Anda gunakan untuk menguji kolom jika memiliki nilai null - terkait dengan null seperti yang terlihat oleh database.

DataRow["col"]==nullakan selalu false.

menggunakan

DataRow r;
if (r.IsNull("col")) ...

sebagai gantinya.

Daniel Mošmondor
sumber
3

Null mirip dengan penunjuk nol di C ++ . Jadi ini adalah referensi yang tidak menunjuk pada nilai apapun .

DBNull.Valuebenar-benar berbeda dan merupakan konstanta yang dikembalikan ketika nilai bidang berisi NULL.

Aliostad
sumber