views:

57

answers:

2

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?

+1  A: 

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...
           };
Dismissile
Thanks! So DateTime? nullableDate = dataRow.Field<DateTime?>("ColumnName"); what would that be in my example?
Sam Gentile
Updated my example....
Dismissile
I got an "Specified cast is not valid."} [System.InvalidCastException]: {"Specified cast is not valid."} Data: {System.Collections.ListDictionaryInternal} HelpLink: null InnerException: null Message: "Specified cast is not valid." Source: "System.Data.DataSetExtensions" StackTrace: " at System.Data.DataRowExtensions.UnboxT`1.NullableField[TElem](Object value)\r\n at System.Data.DataRowExtensions.Field[T](Da
Sam Gentile
...when trying to do CheckInDate = dr.Field<DateTime?>("CHECKIN_DATE"), after defining the field as DateTime?
Sam Gentile
Well...looking closer at your example the schema says CHECKIN_DATE is defined as NOT NULL. No need to change that one to a nullable since it can never be NULL in the database.
Dismissile
So Canceled_DTS is the only field I have to worry about according to that
Sam Gentile
A: 

As only value types can be made Nullable, you won't have to do anything special for strings. Primitive types (and DateTime) can be declared nullable by appending a question mark after their type name, like int? NullableNumber { get; set; }.

Ben
Thanks, that's what I thought
Sam Gentile