I saw this thread on Stack Overflow regarding converting between DBNull and nullable types but I am still confused. I have written code like this with some hack code to deal with nullable types for DateTime and ints that I will show below but it'sa mess and I want to use Nullable types:
 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 is now defined as:
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; }
The database guy tells me that this is the return from Oracle in the DataSet/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
How can I declare RON with Nullable Types and how can I do operations with Nullable Dates and such? Do strings have to be checked?
To define a Value Type (such as DateTime) as Nullable...do one of the following:
DateTime? ReportedDTS
OR
Nullable<DateTime> ReportedDTS
Reference types (such as string) are already "nullable".
To get a nullable value out of a DataRow you can use the field extension method:
DateTime? nullableDate = dataRow.Field<DateTime?>("ColumnName");
That will automatically convert DBNull to null.
So for your example you can do something like:
select new RON
           {
               RONId = dr.Field<string>("RON_ID"),
               // snip...
               CheckInDate = dr.Field<DateTime?>("CHECKIN_DATE"),
               // snip...
           };
                        In reviewing your original question, I see that an error will occur when .ToString() is called on a null value.
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With