2013-08-31 42 views
9

Tôi muốn lấy các giá trị thập phân từ cơ sở dữ liệu và tôi muốn biết đó là cách được khuyến nghị để kiểm tra các giá trị null.SqlDataReader Cách tốt nhất để kiểm tra các giá trị null -sqlDataReader.IsDBNull vs DBNull.Value

Tôi đã xem trên MSDN - DBNull.Value Field rằng séc này hiếm khi được sử dụng.

Do đó, cách reader.IsDBNull là cách tốt nhất/hiệu quả nhất để kiểm tra giá trị rỗng?

Tôi đã tạo ra 2 phương pháp mẫu:

public static decimal? GetNullableDecimal(SqlDataReader reader, string fieldName) 
{ 
    if (reader[fieldName] == DBNull.Value) 
    { 
     return null; 
    } 
    return (decimal)reader[fieldName]; 
} 

public static decimal? GetNullableDecimal_2(SqlDataReader reader, string fieldName) 
{ 
    if (reader.IsDBNull(reader[fieldName])) 
    { 
     return null; 
    } 
    return (decimal)reader[fieldName]; 
} 

Phần lớn thời gian các lĩnh vực sẽ được null.

Cảm ơn trước!

+0

Bạn thích cái nào nhất và dễ đọc nhất. Tuy nhiên, đáng chú ý là các ví dụ của bạn không hoàn toàn tương đương với việc sử dụng 'reader.GetOrdinal' trong lần thứ hai. –

+1

Nội bộ cú pháp 'reader [fieldName]' được giải quyết cho 'reader.GetOrdinal (fieldName)' – Steve

+0

Tôi đã sửa đổi ví dụ để sử dụng trình đọc [fieldName] trong cả hai trường hợp – diver

Trả lời

27

Tôi sẽ không bị cuốn vào phương pháp nào tốt hơn, bởi vì cả hai công việc và tôi đã sử dụng cả hai trong mã trước đây.

Ví dụ, đây là một chức năng hữu ích tôi đào lên từ một trong những dự án cũ của tôi:

/// <summary> 
/// Helper class for SqlDataReader, which allows for the calling code to retrieve a value in a generic fashion. 
/// </summary> 
public static class SqlReaderHelper 
{ 
    private static bool IsNullableType(Type theValueType) 
    { 
     return (theValueType.IsGenericType && theValueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))); 
    } 

    /// <summary> 
    /// Returns the value, of type T, from the SqlDataReader, accounting for both generic and non-generic types. 
    /// </summary> 
    /// <typeparam name="T">T, type applied</typeparam> 
    /// <param name="theReader">The SqlDataReader object that queried the database</param> 
    /// <param name="theColumnName">The column of data to retrieve a value from</param> 
    /// <returns>T, type applied; default value of type if database value is null</returns> 
    public static T GetValue<T>(this SqlDataReader theReader, string theColumnName) 
    { 
     // Read the value out of the reader by string (column name); returns object 
     object theValue = theReader[theColumnName]; 

     // Cast to the generic type applied to this method (i.e. int?) 
     Type theValueType = typeof(T); 

     // Check for null value from the database 
     if (DBNull.Value != theValue) 
     { 
      // We have a null, do we have a nullable type for T? 
      if (!IsNullableType(theValueType)) 
      { 
       // No, this is not a nullable type so just change the value's type from object to T 
       return (T)Convert.ChangeType(theValue, theValueType); 
      } 
      else 
      { 
       // Yes, this is a nullable type so change the value's type from object to the underlying type of T 
       NullableConverter theNullableConverter = new NullableConverter(theValueType); 

       return (T)Convert.ChangeType(theValue, theNullableConverter.UnderlyingType); 
      } 
     } 

     // The value was null in the database, so return the default value for T; this will vary based on what T is (i.e. int has a default of 0) 
     return default(T); 
    } 
} 

Cách sử dụng:

yourSqlReaderObject.GetValue<int?>("SOME_ID_COLUMN"); 
yourSqlReaderObject.GetValue<string>("SOME_VALUE_COLUMN"); 
+1

Tuyệt vời! Tôi chỉ có một đề xuất để điều chỉnh cho điều này .. thay đổi GetValue này SqlDataReader thành GetValue (IDataRecord này – KevinDeus

6

Nếu bạn muốn kiểm tra cho null và xử lý nó (như trái ngược với việc kiểm tra null và cảnh báo chương trình là null), bạn có thể sử dụng toán tử as với toán tử không hợp nhất ??. Vì vậy, trong chương trình của tôi

SqlDataReader dr = cmd.ExecuteReader(); 
while (dr.Read()) 
{ 
    response.Employees.Add(new Employee() { Id = dr["id"] as int? ?? default(int), ImageUrl = dr["Photo"] as string, JobTitle = dr["JobTitle"] as string }); 
} 
+0

Mẹo gọn gàng, cảm ơn bạn đã chia sẻ! – Jocie

1

Dưới đây là một phiên bản đơn giản của câu trả lời @Karl Anderson:

public static class DbHelper 
{ 
    public static T GetValue<T>(this SqlDataReader sqlDataReader, string columnName) 
    { 
     var value = sqlDataReader[columnName]; 

     if (value != DBNull.Value) 
     { 
      return (T)value; 
     } 

     return default(T); 
    } 
} 

Hoặc thậm chí:

public static class DbHelper 
{ 
    public static T GetValue<T>(this SqlDataReader sqlDataReader, string columnName) 
    { 
     var value = sqlDataReader[columnName]; 

     return value == DBNull.Value ? default(T) : (T) value; 
    } 
} 

đúc trực tiếp dường như chỉ làm việc tốt cho cả hai nullable hoặc các loại không thể null.

Các vấn đề liên quan