2008-10-20 18 views
47

Tôi có một số DateTime? mà tôi đang cố gắng chèn vào một trường bằng cách sử dụng DbParameter. Tôi đang tạo ra các thông số như sau:C# ADO.NET: nulls và DbNull - có cú pháp hiệu quả hơn không?

DbParameter datePrm = updateStmt.CreateParameter(); 
datePrm.ParameterName = "@change_date"; 

Và sau đó tôi muốn đặt giá trị của DateTime? vào dataPrm.Value khi chiếm null s.

tôi nghĩ ban đầu tôi muốn được thông minh:

datePrm.Value = nullableDate ?? DBNull.Value; 

nhưng điều đó không thành công với các lỗi

Operator '??' không thể áp dụng cho các toán hạng kiểu 'System.DateTime?' và 'System.DBNull'

Vì vậy, tôi đoán rằng chỉ hoạt động nếu đối số thứ hai là phiên bản không thể vô hiệu của đối số đầu tiên. Vì vậy, sau đó tôi đi cho:

datePrm.Value = nullableDate.HasValue ? nullableDate.Value : DBNull.Value; 

nhưng điều đó không làm việc, hoặc:

Loại biểu thức điều kiện không xác định được vì không có chuyển đổi ngầm giữa 'System.DateTime' và 'System. DBNull '

Nhưng tôi không muốn chuyển đổi giữa các loại đó!

Cho đến nay điều duy nhất tôi có thể nhận được để làm việc là:

if (nullableDate.HasValue) 
    datePrm.Value = nullableDate.Value; 
else 
    datePrm.Value = DBNull.Value; 

Đó là thực sự là cách duy nhất tôi có thể viết này? Có cách nào để có được một lớp lót bằng cách sử dụng toán tử ternary để hoạt động không?

Cập nhật: Tôi thực sự không hiểu tại sao ?? phiên bản không hoạt động. MSDN nói:

?? toán tử trả về toán hạng bên trái nếu nó không phải là null, nếu không nó sẽ trả về toán hạng bên phải.

Đó chính xác là những gì tôi muốn!

Update2: Vâng đó là loại rõ ràng cuối cùng:

datePrm.Value = nullableDate ?? (object)DBNull.Value; 
+0

http://stackoverflow.com/questions/1545711/is-it-possible-to-coalesce-string-and- dbnull-in-c – JohnB

Trả lời

61

Ah ha! Tôi tìm thấy một giải pháp hiệu quả hơn cả @ Trebz!

datePrm.Value = nullableDate ?? (object)DBNull.Value; 
+1

Tôi sẽ không gọi nó là "hiệu quả" có lẽ "súc tích là một từ tốt hơn? –

+0

Phải - bạn biết ý tôi là gì. :-) –

+0

Điều này thực sự tuyệt vời! Tôi đã tìm kiếm điều này. Cảm ơn – Brian

5

Nó sẽ có tác dụng nếu bạn sử dụng

datePrm.Value = nullableDate.HasValue ? (object)nullableDate.Value : DBNull.Value; 
+0

Đúng, cái đó hoạt động tốt và ngắn hơn 8 ký tự của giải pháp @ Dan. :-) Tôi muốn có một cách để có được ?? giải pháp để làm việc vì cú pháp ngắn hơn nhiều. –

+0

Cập nhật: Tôi đã tìm thấy một giải pháp hiệu quả hơn bằng cách sử dụng ??. –

1

Tôi nghĩ rằng lỗi với nỗ lực thứ hai của bạn là do nullableDate .Value và DBNull.Value là các kiểu khác nhau và toán tử bậc ba cần chọn một kiểu để trả về trong cả hai trường hợp.Tôi không có môi trường để kiểm tra điều này nhưng tôi nghĩ rằng điều này sẽ làm việc cho bạn:

datePrm.Value = nullableDate.HasValue ? (object)nullableDate.Value : (object)DBNull.Value; 
0

Cách mà tôi làm điều đó, là tôi có một lớp tiện ích tĩnh mà chỉ đi qua và kiểm tra xem nếu giá trị tham số là null, sau đó tôi đặt giá trị để làm DBNull. Tôi chỉ làm điều đó trước khi tôi gọi Execute.

6

Nếu bạn đang sử dụng C# 3.0 bạn có thể tạo ra một phương pháp khuyến nông để làm điều này dễ dàng:

public static class DBNullableExtensions 
{ 
    public static object ToDBValue<T>(this Nullable<T> value) where T:struct 
    { 
     return value.HasValue ? (object)value.Value : DBNull.Value; 
    } 
} 


class Program 
{ 
    static void Main(string[] args) 
    { 
     int? x = null; 

     Console.WriteLine( x.ToDBValue() == DBNull.Value); 
    } 
} 
5

Nếu bạn đang sử dụng SQLServer, không gian tên System.Data.SqlTypes chứa một số lớp tiện ích tránh loại gây khó chịu. Ví dụ thay vì điều này:

var val = (object) "abc" ?? DBNull.Value; 

bạn có thể viết này:

var val = "abc" ?? SqlString.Null; 
+0

+1 @Gian Marco Gherardi là câu trả lời lý tưởng. Bạn vẫn có thể sử dụng toán tử bậc ba, chỉ cần sử dụng các lớp trợ giúp được cung cấp bởi System.Data.SqlTypes –