Sự khác biệt giữa null và System.DBNull.Value là gì?


91

Có sự khác biệt nào giữa null và System.DBNull.Value không? Nếu có, nó là cái gì?

Tôi nhận thấy hành vi này bây giờ -

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

Trong khi tôi truy xuất dữ liệu từ cơ sở dữ liệu bằng cách sử dụng bộ dữ liệu sql, mặc dù không có giá trị nào được trả if(rdr["Id"] != null)về truevà cuối cùng đã ném ra một ngoại lệ để truyền null thành số nguyên.

Nhưng, điều này nếu tôi sử dụng if (rdr["Id"] != System.DBNull.Value)lợi nhuận false.

Sự khác biệt giữa null và System.DBNull.Value là gì?


Chà, chúng không liên quan. Một là thể hiện tĩnh của một lớp trong System.Datavà một là giá trị đặc biệt biểu thị sự thiếu tham chiếu. Họ không có gì để làm với nhau. Bạn có thể nói rõ hơn về những gì bạn đang bối rối không? Câu hỏi thực sự của bạn là "tại sao phải làm DataRowsDataReadersđặt DBNull.Valuebên trong của chúng thay vì null?"
mqp

Chà, ban đầu thì không phải vậy nhưng sau khi học từ những gì bạn nói, tôi rất tò mò. Bạn có thể cho tôi biết tại sao DataRows và DataReaders lại đặt DBNull.Value thay vì null không?
pavanred

Bản thân tôi cũng không chắc nữa. Đây là một câu trả lời: stackoverflow.com/questions/4488727/what-is-the-point-of-dbnull/… Cũng có thể là trước khi các loại giá trị nullable xuất hiện trong C #, nó sẽ phức tạp hơn để giải quyết null.
mqp

1
Tôi đã có câu trả lời ở đây, nhưng tôi nhận ra rằng nó phù hợp hơn cho stackoverflow.com/questions/4488727/what-is-the-point-of-dbnull - vì vậy tôi đã chuyển nó
Marc Gravell

Câu trả lời:


115

Vâng, nullkhông phải là một ví dụ của bất kỳ loại nào. Đúng hơn, nó là một tham chiếu không hợp lệ.

Tuy nhiên, System.DbNull.Valuelà một tham chiếu hợp lệ đến một thể hiện của System.DbNull( System.DbNulllà một singleton và System.DbNull.Valuecung cấp cho bạn một tham chiếu đến thể hiện duy nhất của lớp đó) đại diện cho các giá trị * không tồn tại trong cơ sở dữ liệu.

* Chúng tôi thường nói null, nhưng tôi không muốn làm xáo trộn vấn đề.

Vì vậy, có một sự khác biệt lớn về khái niệm giữa cả hai. Từ khóa nullđại diện cho một tham chiếu không hợp lệ. Lớp System.DbNullđại diện cho một giá trị không tồn tại trong một trường cơ sở dữ liệu. Nói chung, chúng ta nên cố gắng tránh sử dụng cùng một thứ (trong trường hợp này null) để biểu thị hai khái niệm rất khác nhau (trong trường hợp này là tham chiếu không hợp lệ so với giá trị không tồn tại trong trường cơ sở dữ liệu).

Hãy nhớ rằng, đây là lý do tại sao nhiều người ủng hộ việc sử dụng mẫu đối tượng null nói chung, đây chính xác System.DbNulllà ví dụ về.


43
+1 Một ví dụ thực tế: nếu bạn sử dụng IDbCommand.ExecuteScalar(), nó có thể trả về null (không có bản ghi nào được trả về) hoặc DbNull(cột đầu tiên trong bản ghi đầu tiên là 'giá trị không tồn tại'). Nếu không có DbNullbạn sẽ không thể phân biệt cái này với cái kia.
C.Evenhuis 19/02/13

Tôi thực sự khuyên bạn nên sử dụng một ngôn ngữ cấm sử dụng Null và làm như vậy với chi phí hoàn toàn là 0. cuộc sống quá ngắn đối với "mẫu đối tượng null"
nicolas

3
Tham chiếu rỗng là hoàn toàn hợp lệ. ☺
IllidanS4 muốn Monica trở lại

@ C.Evenhuis Chà, có một lời khuyên phổ biến khác: một hàm chỉ nên trả về một loại giá trị. Đó là lý do tại sao mọi người thích mã TypeScript được đánh máy tốt. "Trạng thái thực hiện là gì" khác với "Kết quả tính toán là gì". I E. họ có thể đã quyết định triển khai chức năng này bằng cách nào khác (có thể là tham số out hoặc một đối tượng tương tự như các đối tượng phản hồi yêu cầu HTTP). Chắc chắn, đây là một sự phức tạp không thực sự mong muốn, nhưng nếu họ đã làm điều đó, có thể null có thể được sử dụng thay vì DbNull.
klenium

21

Từ tài liệu của lớp DBNull :

Đừng nhầm lẫn khái niệm null trong ngôn ngữ lập trình hướng đối tượng với đối tượng DBNull. Trong ngôn ngữ lập trình hướng đối tượng, null có nghĩa là không có tham chiếu đến một đối tượng. DBNull đại diện cho một biến thể chưa được khởi tạo hoặc cột cơ sở dữ liệu không tồn tại.


11

DBNull.Value thật khó chịu khi phải đối phó.

Tôi sử dụng các phương thức tĩnh để kiểm tra xem đó có phải là DBNull hay không và sau đó trả về giá trị.

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

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

Ngoài ra, khi chèn giá trị vào DataRow, bạn không thể sử dụng "null", bạn phải sử dụng DBNull.Value.

Có hai đại diện của "null" là một thiết kế tồi không mang lại lợi ích rõ ràng.


2
Những tình cảm của chúng ta ghê tởm phần tái: tuyên bố cuối cùng của bạn là vu cáo chỉ bởi sự trớ trêu của hiển thị vào đây để đọc và tìm ra tên người dùng của bạn là "ghê tởm"
Iofacture

5

DBNull.Value là những gì mà nhà cung cấp Cơ sở dữ liệu .NET trả về để đại diện cho mục nhập rỗng trong cơ sở dữ liệu. DBNull.Value không phải là null và các phép so sánh thành null đối với các giá trị cột được truy xuất từ ​​một hàng cơ sở dữ liệu sẽ không hoạt động, bạn phải luôn so sánh với DBNull.Value.

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


ps Bạn cũng nên sử dụng DBNull.Value để truyền một tham số null vào cơ sở dữ liệu, nếu không, nó có thể được hiểu là tham số không được truyền.
James Michael Hare

1
DBNull không phải là "cái mà cơ sở dữ liệu trả về" - nó chỉ đơn giản là cách ADO.NET chọn để diễn giải nó; cá nhân tôi không chắc rằng cách giải thích này rất có giá trị
Marc Gravell

@MarcGravell Vâng, Marc, bạn nói đúng. Tôi đã nói điều đó không chính xác. ASP.NET dịch cơ sở dữ liệu giá trị cột rỗng vào DBNull.Value
James Michael Hare

3

DataRow có một phương thức được gọi IsNull()mà bạn có thể sử dụng để kiểm tra cột nếu nó có giá trị null - liên quan đến giá trị null khi nó được cơ sở dữ liệu nhìn thấy.

DataRow["col"]==nulltất cả sẽ được false.

sử dụng

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

thay thế.


3

Null tương tự như con trỏ không trong C ++ . Vì vậy, nó là một tham chiếu không trỏ đến bất kỳ giá trị nào .

DBNull.Valuehoàn toàn khác và là một hằng số được trả về khi giá trị trường chứa NULL.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.