2010-10-28 12 views
5

Ho visto this thread su Stack Overflow relativo alla conversione tra tipi DBNull e nullable, ma sono ancora confuso. Ho scritto il codice come questo con un po 'di codice trucco a che fare con tipi nullable per DateTime e interi che io ti indicherò di seguito, ma si tratta di un pasticcio e voglio usare tipi Nullable:Problemi con i tipi Nullable, DBNulls e Righe dati

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 è ora definito come:

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; } 

il ragazzo banca dati mi dice che questo è il ritorno da Oracle nel DataSet/cursore:

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 

Come posso dichiarare con RON tipi nullable e come posso fare operazioni con Nu Date lilla e così? Le stringhe devono essere controllate?

risposta

6

Per definire un tipo di valore (come DateTime) come Nullable ... fare una delle seguenti:

DateTime? ReportedDTS 

O

Nullable<DateTime> ReportedDTS 

I tipi di riferimento (come stringa) sono già " annullabile".

per ottenere un valore nullable di un DataRow è possibile utilizzare il metodo di estensione campo:

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

che converte automaticamente DBNull a NULL.

Così, per il tuo esempio si può fare qualcosa di simile:

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

Grazie! Quindi DateTime? nullableDate = dataRow.Campo ("NomeColonna"); che cosa sarebbe nel mio esempio? –

+0

Aggiornato il mio esempio .... – Dismissile

+0

Ho ottenuto un "Cast specificato non valido."} [System.InvalidCastException]: {"Cast specificato non valido."} Dati: {System.Collections.ListDictionaryInternal} HelpLink : null InnerException: null Messaggio: "Il cast specificato non è valido." Origine: "System.Data.DataSetExtensions" StackTrace: "su System.Data.DiDataRowExtensions.UnboxT'1.NullableField [TElem] (valore oggetto) \ r \ n su System.Data.DataRowExtensions.Field [T] (Da –

0

Come solo i tipi di valore possono essere fatte Nullable, non dovrete fare nulla di speciale per le stringhe. I tipi primitivi (e DateTime) possono essere dichiarati annullabili aggiungendo un punto interrogativo dopo il loro nome tipo, ad esempio int? NullableNumber { get; set; }.

+0

Grazie, ecco cosa ho pensato –

0

Potrebbe essere necessario confrontare con DBNull prima di assegnare o un DateTime o null

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

Nel rivedere la tua domanda iniziale, vedo che si verifica un errore quando .ToString() è chiamato su un valore nullo.

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 il set di dati per i valori di campo a partita. Qui, ho assunto che il set di dati "ColumnName" avesse lo stesso nome della variabile a cui è stato passato, ma non è sempre così.
  • Word of advice, utilizzare "ColumnName" anziché indice poiché l'indice può cambiare quando cambia db, stored proc o la query cambia.
Problemi correlati