2013-08-30 40 views
6

thế nào chúng ta đọc các giá trị số nguyên null từ Sql dữ liệu đọcgiá trị số nguyên Nullable từ đọc

SqlDataReader reader = cmd.ExecuteReader(); 
if (reader.Read() == true) 
{ 
    mb.Id = (int)reader["Id"]; 
    mb.Mem_NA = (string)reader["Mem_NA"]; 
    mb.Mem_ResAdd4 = reader["Mem_ResAdd4"] == System.DBNull.Value ? null : (string)reader["Mem_ResAdd4"]; 
    // 
    mb.Mem_ResPin = reader["Mem_ResPin"] as int? ?? default(int); 
    // shows the error "Object cannot be cast from DBNull to other types." 
} 

mb.Mem_ResPin không thể đọc từ reader

CREATE TABLE [dbo].[Mem_Basic] (
[Id]   INT   IDENTITY (1, 1) NOT NULL, 
[Mem_NA]  VARCHAR (100) NOT NULL, 
[Mem_ResAdd4] VARCHAR (100) NULL, 
[Mem_ResPin] INT   NULL, 
PRIMARY KEY CLUSTERED ([Id] ASC) 
); 
+0

'mb.Mem_ResPin' được khai báo là gì? – ChrisF

+2

Tôi biết chúng tôi đã có cuộc trò chuyện này, nhưng "dapper" sẽ chỉ * thực hiện công việc này * mà không có bạn đập đầu vào ADO.NET mỗi bước của cách ... chỉ cần nói - 'có một lý do chúng tôi đã viết nó. ..để tránh * chính xác * loại đau đớn này –

+0

@Marc, và tôi có thể ** hoàn toàn ** chứng thực tại sao Dapper là ** ORM tốt nhất ** trên thị trường hiện nay! Và nó hoàn toàn miễn phí! –

Trả lời

8

Chỉ cần chuyển đổi nó, giống như bạn làm trong hàng trước

mb.Mem_ResAdd4 = reader["Mem_ResAdd4"] == System.DBNull.Value ? null : (string)reader["Mem_ResAdd4"]; 
// 
    mb.Mem_ResPin = reader["Mem_ResPin"]== System.DBNull.Value ? default(int):(int)reader["Mem_ResPin"] 
+0

hiển thị lỗi "Đối tượng không thể truyền từ DBNull sang các loại khác". – neel

+0

xem phản ứng của tôi đối với xử lý DBNull –

1

So sánh là chống lại DBNull.

var resPin = reader["Mem_ResPin"]; 
if(!Convert.IsDBNull(resPin)) 
    mb.Mem_ResPin = resPin as int?; 
else 
    mb.Mem_ResPin = new Nullable<int>(); 
+0

cho thấy lỗi không thể chuyển đổi int kiểu int? vào int – neel

+0

Bạn có chắc 'mb.Mem_ResPin' là một kiểu' int? '? – keyboardP

2

Có một vài cách tiếp cận tại đây. Thật không may, DBNull làm cho sự thất vọng này - API reader[name] trả về số object có thể là giá trị của bạn hoặc có thể là DBNull.Value - vì vậy bạn phải kiểm tra điều đó (is) và xử lý. Cách tiếp cận khác là sử dụng API reader.IsDBNull(ordinal), nhưng như bạn sẽ lưu ý: cần có thứ tự (chỉ mục cột) thay vì một tên . Trong cả hai trường hợp, bạn có thể thêm những thứ như phương pháp hữu ích để giúp:

static object Read(IDataReader reader, string name) 
{ 
    var val = reader[name]; 
    return val is DBNull ? (object)null : val; 
} 

sau đó (ví dụ):

mb.Mem_ResPin = (int?)Read(reader, "Mem_ResPin") 

Tuy nhiên, một lần nữa: các công cụ như "đoan trang" có thể làm cho điều này dễ dàng hơn nhiều cho bạn; một đơn Query<T>(tsql, args).SingleOrDefault() sẽ xử lý tất cả những điều này, bao gồm cả null, Nullable<T> và một loạt các tình huống khác.

+0

Mã này sẽ dẫn đến lỗi truyền khi truyền tới (int?). Trước tiên, bạn cần phải mở hộp thư đến một int thông thường. –

+0

@MennovandenHeuvel không, bạn không. Thử nó. Tồi tệ hơn: unboxing thành 'int' (thay vì' int? ') Sẽ thực sự làm cho nó ném một' NullReferenceException' bất cứ khi nào giá trị là 'null' (đây rõ ràng là một kịch bản dự kiến ​​ở đây) –

3

Viết trình bao bọc đơn giản, ví dụ: như một phương pháp mở rộng và kiểm tra IsDBNull bên:

public static int SafeGetInt(this SqlDataReader reader, string colName) 
{ 
    var colIndex = reader.GetOrdinal(colName); 
    return !reader.IsDBNull(colIndex) ? reader.GetInt32(colIndex) : default(int); 
} 

sử dụng:

var result = reader.SafeGetInt(colName); 
1

tôi sử dụng một phương pháp khuyến nông chung cho tất cả các DB phôi:

public static T? DbCast<T>(this object dbValue) 
     where T : struct 
    { 
     if (dbValue == null) 
     { 
      return null; 
     } 
     if (dbValue is System.DBNull) 
     { 
      return null; 
     } 
     T? value = dbValue as T?; 
     if (value != null) 
     { 
      return value; 
     } 
     var conv = dbValue as IConvertible; 
     if (conv != null) 
     { 
      value = (T)conv.ToType(typeof(T), CultureInfo.InvariantCulture); 
     } 
     return value; 
    } 

cố gắng đối xử với mọi tình huống i gặp phải trong mã của chúng tôi. Điều chỉnh các điều kiện cần thiết cho tình huống của bạn.

Cách sử dụng:

int? value = reader["Mem_ResAdd4"].DbCast<int>() 
2

Có thể thử gia hạn này:

public static class Helper 
{ 
    public static T GetSafe<T>(this SqlDataReader reader, string name) 
    { 
     var value = reader[name]; 
     return value == DBNull.Value ? default(T) : (T) value; 
    } 
} 

và sử dụng như thế này:

 if (reader.Read()) 
     { 
      Mb mb = new Mb(); 
      mb.Id = reader.GetSafe<int>("Id"); 
      mb.Mem_NA = reader.GetSafe<string>("Mem_NA"); 
      mb.Mem_ResAdd4 = reader.GetSafe<string>("Mem_ResAdd4"); 

      mb.Mem_ResPin = reader.GetSafe<int>("ResPin"); 
     } 
1

Bạn có thể sử dụng để xử lý SqlDataReader.GetSqlInt32Nullable<int>:

SqlInt32 resPin = reader.GetSqlInt32(reader.GetOrdinal("Mem_ResPin")); 
mb.Mem_ResPin = resPin.IsNull ? (int?) null : resPin.Value; 
Các vấn đề liên quan