2010-10-28 15 views
5

Vi this thread en Stack Overflow con respecto a la conversión entre DBNull y tipos anulables, pero todavía estoy confundido. He escrito un código como éste con algo de código truco para hacer frente a los tipos anulables para DateTime y intercepciones que voy a mostrar a continuación pero es un lío y quiero usar tipos anulables:Problema con tipos anulables, DBNulls y filas de datos

DataTable dt = ds.Tables[0]; 
List<RON> list = (from dr in dt.AsEnumerable() 
           select new RON 
           { 
            RONId = dr[0].ToString(), 
            StaffNumber = dr[1].ToString(), 
            CheckInDate = GetCheckInDate(dr[2]), 
            NonMissionIndicator = dr[3].ToString(), 
            Comments = dr[4].ToString(), 
            NonComplyIndicator = dr[5].ToString(), 
            LOAirport = dr[6].ToString(), 
            RONAirport = dr[7].ToString(), 
            PropertyId = GetPropertyId(dr[8]), 
            PropertyChain = dr[9].ToString(), 
            PropertyName = dr[10].ToString(), 
            PropertyStreet = dr[11].ToString(), 
            PropertyStreet2 = dr[12].ToString(), 
            PropertyCity = dr[13].ToString(), 
            PropertyState = dr[14].ToString(), 
            PropertyPostalCode = dr[15].ToString(), 
            PropertyPhone = dr[16].ToString(), 
            FAX = dr[17].ToString(), 
            PropertyCountry = dr[18].ToString(), 
            PropertyLongitude = GetPropertyLongitude(dr[19]), 
            PropertyLatitude = GetPropertyLatitude(dr[20]), 
            PropertyAirport = dr[21].ToString(), 
            ReportedBy = dr[22].ToString(), 
            ReportedDTS= GetReportedByDate(dr[23]), 
            CanceledBy = dr[24].ToString(), 
            CanceledDTS = GetCanceledByDate(dr[25]) 
           }).ToList(); 
      return list; 
     } 

     //TODO: Change Defaukt date 
     private static DateTime GetCheckInDate(object checkInDate) 
     { 
      return checkInDate == DBNull.Value ? new DateTime(2000, 1, 1, 00, 00, 00) : Convert.ToDateTime(checkInDate); 
     } 

     //TODO: Change Defaukt date 
     private static DateTime GetReportedByDate(object reportedByDate) 
     { 
      return reportedByDate == DBNull.Value ? new DateTime(2000, 1, 1, 00, 00, 00) : Convert.ToDateTime(reportedByDate); 
     } 

     //TODO: Change Defaukt date 
     private static DateTime GetCanceledByDate(object canceledByDate) 
     { 
      return canceledByDate == DBNull.Value ? new DateTime(2000, 1, 1, 00, 00, 00) : Convert.ToDateTime(canceledByDate); 
     } 

     private static Int32 GetPropertyId(object propertyId) 
     { 
      return propertyId == DBNull.Value ? 0 : Convert.ToInt32(propertyId); 
     } 

     private static double GetPropertyLongitude(object propertyLongitude) 
     { 
      return propertyLongitude == DBNull.Value ? 0.0 : Convert.ToDouble(propertyLongitude); 
     } 

     private static double GetPropertyLatitude(object propertyLatitude) 
     { 
      return propertyLatitude == DBNull.Value ? 0.0 : Convert.ToDouble(propertyLatitude); 
     } 

RON ahora se define como:

public class RON 
    { 
     public string RONId { get; set; } 
     public string StaffNumber { get; set; } 
     public DateTime CheckInDate { get; set; } 
     public string NonMissionIndicator { get; set; } 
     public string NonComplyIndicator { get; set; } 
     public string LOAirport { get; set; } 
     public string RONAirport { get; set; } 
     public int PropertyId { get; set; } 
     public string PropertyChain { get; set; } 
     public string PropertyName { get; set; } 
     public string PropertyStreet { get; set; } 
     public string PropertyStreet2 { get; set; } 
     public string PropertyCity { get; set; } 
     public string PropertyState { get; set; } 
     public string PropertyPostalCode { get; set; } 
     public string PropertyCountry { get; set; } 
     public string PropertyPhone { get; set; } 
     public string FAX { get; set; } 
     public double PropertyLongitude { get; set; } 
     public double PropertyLatitude { get; set; } 
     public string PropertyAirport { get; set; } 
     public string ReportedBy { get; set; } 
     public DateTime ReportedDTS { get; set; } 
     public string CanceledBy { get; set; } 
     public DateTime CanceledDTS { get; set; } 
     public string Comments { get; set; } 

el tipo de base de datos me dice que este es el regreso de Oracle en el conjunto de datos/cursor:

RON_ID         NOT NULL VARCHAR2(40) 
STAFF_NUM         NOT NULL VARCHAR2(12) 
CHECKIN_DATE        NOT NULL DATE 
NONMISSION_IND       NOT NULL VARCHAR2(1) 
COMMENTS           VARCHAR2(4000) 
NONCOMPLY_IND          VARCHAR2(4000) 
PROPERTY_ID        NOT NULL NUMBER(38) 
PROPERTY_CHAIN          VARCHAR2(2) 
PROPERTY_NAME          VARCHAR2(255) 
RON_AIRPORT        NOT NULL VARCHAR2(3) 
PROPERTY_STREET         VARCHAR2(255) 
PROPERTY_STREET2         VARCHAR2(255) 
PROPERTY_CITY          VARCHAR2(255) 
PROPERTY_STATE          VARCHAR2(3) 
PROPERTY_POSTALCODE        VARCHAR2(255) 
PROPERTY_PHONE          VARCHAR2(20) 
PROPERTY_FAX          VARCHAR2(20) 
PROPERTY_COUNTRY         VARCHAR2(2) 
PROPERTY_LONGITUDE         NUMBER 
PROPERTY_LATITUDE         NUMBER 
PROPERTY_AIRPORT         VARCHAR2(3) 
REPORTED_BY          VARCHAR2(50) 
REPORTED_DTS        NOT NULL DATE 
CANCELED_BY          VARCHAR2(50) 
CANCELED_DTS          DATE 

¿Cómo puedo declarar RON con tipos anulables y cómo puedo hacer operaciones con Nu fechas Dable y tal? ¿Las cuerdas deben ser revisadas?

Respuesta

6

para definir un tipo de valor (como DateTime) como anulable ... realice una de las siguientes:

DateTime? ReportedDTS 

O

Nullable<DateTime> ReportedDTS 

Tipos de referencia (como cadena) están ya " nullable ".

para obtener un valor anulable cabo de un DataRow puede utilizar el método de extensión de campo:

DateTime? nullableDate = dataRow.Field<DateTime?>("ColumnName"); 

que convertirá automáticamente DBNull en nulo.

Así que para su ejemplo, usted puede hacer algo como:

select new RON 
      { 
       RONId = dr.Field<string>("RON_ID"), 
       // snip... 
       CheckInDate = dr.Field<DateTime?>("CHECKIN_DATE"), 
       // snip... 
      }; 
+0

Gracias! Entonces, ¿DateTime? nullableDate = dataRow.Campo ("ColumnName"); ¿qué sería eso en mi ejemplo? –

+0

actualizado mi ejemplo .... – Dismissile

+0

Tengo una } [System.InvalidCastException] "la conversión especificada no es válida.": { "La conversión especificada no es válida."} de datos: {} System.Collections.ListDictionaryInternal HelpLink : null InnerException: null Mensaje: "El molde especificado no es válido". Fuente: "System.Data.DataSetExtensions" StackTrace: "en System.Data.DataRowExtensions.UnboxT'1.NullableField [TElem] (Valor del objeto) \ r \ n en System.Data.DataRowExtensions.Field [T] (Da –

0

tipos de valor Como sólo se pueden hacer Nullable, usted no tendrá que hacer nada especial para cadenas. Los tipos primitivos (y DateTime) pueden declararse anulables al agregar un signo de interrogación después de su nombre de tipo, como int? NullableNumber { get; set; }.

+0

Gracias, eso es lo pensé –

0

Es posible que tenga que comparar DBNull antes de asignar o bien un DateTime o nula

myNullableDate = (DBNull.Value == list.Field<object>("FOO")) 
      ? null 
      : (DateTime?)list.Field<DateTime?>("FOO"); 
0

Al revisar su pregunta original, veo que se producirá un error cuando .ToString() es llamado en un valor nulo.

This happens when the dataset field has a DBNULL value. 
The Best approach is to test for null first before calling any methods on the object. 
i.e.

DataTable dt = ds.Tables[0]; List<RON> list = (from dr in dt.AsEnumerable() select new RON { RONId = dr.IsNull("RONid") ? "0" : dr.Field<String>("RONid"), StaffNumber = dr.IsNull("StaffNumber") ? "0" : dr.Field<String>("StaffNumber"), ... etc, ... etc }).ToList(); return list; }

PS:

  • sonda conjunto de datos para los valores de campo para que coincida. Aquí, asumí que su conjunto de datos "ColumnName" tenía el mismo nombre que la variable a la que se le pasa, pero ese no es siempre el caso.
  • Como consejo, utilice "ColumnName" en lugar de índice, ya que el índice puede cambiar cuando cambia db, se almacena el proceso o su consulta cambia.
Cuestiones relacionadas