reggie
reggie

Reputation: 858

validating null value conversions

I have a class named project with the following data members.

class Project
{
    private int Record_Num;
    private int GCD_ID;
    private string Project_Desc;
    private string Proponent_Name;
    private string Station_ID;
    private string OpCentre;
    private string Sector_ID;
    private string PLZone;
    private string Feeder_ID;
    private string DxTx_ID;
    private string OpControl_ID;
    private string Type_ID;
    private string ConnKV_ID;
    private string Status_ID;
    private double MW;
    private string Subject;
    private int Ip_Num;
    private int H1N_ID;
    private int NOMS_Slip_Num;
    private DateTime NMS_Updated;
    private DateTime Received_Date;
    private Nullable<DateTime> Actual_IS_Date;
    private string Scheduled_IS_Date;
    private string UP_Station_ID;
    private string UP_Feeder_ID;
    private string HV_Circuit;
}

i query the database and retrieve the values through a data table which assigns the value to the project object like this.

for (int prjIdx = 0; prjIdx < dt.Rows.Count; prjIdx++)
            {
                newProject = new Project(Convert.ToInt32(dt.Rows[prjIdx]["RecordNum"].ToString()), Convert.ToInt32(dt.Rows[prjIdx]["GCDID"].ToString()),
                    dt.Rows[prjIdx]["ProjectDesc"].ToString(), dt.Rows[prjIdx]["ProponentName"].ToString(),
                    dt.Rows[prjIdx]["StationName"].ToString(), dt.Rows[prjIdx]["OpCentre"].ToString(),
                    dt.Rows[prjIdx]["SectorName"].ToString(), dt.Rows[prjIdx]["PLZone"].ToString(),
                    dt.Rows[prjIdx]["FeederDesc"].ToString(), dt.Rows[prjIdx]["DxTx"].ToString(),
                    dt.Rows[prjIdx]["OpControl"].ToString(), dt.Rows[prjIdx]["Type"].ToString(),
                    dt.Rows[prjIdx]["ConnectionKV"].ToString(), dt.Rows[prjIdx]["Status"].ToString(),
                    Convert.ToDouble(dt.Rows[prjIdx]["MW"]), dt.Rows[prjIdx]["Subject"].ToString(),
                    Convert.ToInt32(dt.Rows[prjIdx]["IpNum"]), Convert.ToInt32(dt.Rows[prjIdx]["H1NID"]),
                    Convert.ToInt32(dt.Rows[prjIdx]["NomsSlipNum"]),Convert.ToDateTime(dt.Rows[prjIdx]["NmsUpdated"]),
                    Convert.ToDateTime(dt.Rows[prjIdx]["ReceivedDate"]),Convert.ToDateTime(dt.Rows[prjIdx]["ActualIsDate"]),
                    dt.Rows[prjIdx]["ScheduledIsDate"].ToString(),dt.Rows[prjIdx]["UpStation"].ToString(),dt.Rows[prjIdx]["UpFeeder"].ToString(),
                    dt.Rows[prjIdx]["HVCircuit"].ToString());

                newProject.record_num = Convert.ToInt32(dt.Rows[prjIdx]["RecordNum"]);
                projList.Add(newProject);

            }

now my problem is, all the date time values retrieved from the database can be null.so if it encounters a null value, it fails to convert it and hence it cannot be assigned in to the object. thus it give me an error

how do i tackle the proble. should i change the date time variable to string data type. but thats a lame solution. please help//

Upvotes: 1

Views: 663

Answers (5)

Dynami Le Savard
Dynami Le Savard

Reputation: 5036

DateTime is a value-type, you could use the nullable datetime (DateTime?)

MSDN Ref on Nullable Structure

[...]
private int NOMS_Slip_Num;
private DateTime? NMS_Updated;
private DateTime? Received_Date;
private Nullable<DateTime> Actual_IS_Date;
[...]

Doing so will require changes in how you retrieve the value. One way to do so, would be to implement a null or DBNull check, and set the value of nullable datetimes in the Project instanciation using a ternary operator.

public static class Extensions
{
    public static bool IsNull(this object o)
    {
        if (o == null || DBNull.Value.Equals(o))
            return true;
        else
            return false;
    }
}

and use it like this in Project's instanciation :

var receivedDate = dt.Rows[prjIdx]["ReceivedDate"];
var actualDate = dt.Rows[prjIdx]["ActualIsDate"];
newProject = new Project([...],
                       receivedDate.IsNull() ? null : Convert.ToDateTime(receivedDate),
                       actualDate.IsNull() ? null : Convert.ToDateTime(actualDate),
                       [...]);

Upvotes: 4

Josh
Josh

Reputation: 44916

As everyone has already stated you can use Nullable Types in your Model. As for getting them out of the row and checking for DBNull, MS was smart enough to think of this already, and provided a set of extension methods to do just that.

DataRowExtensions.Field Method

...  
dt.Rows[prjIdx].Field<Int32?>("IpNum");  
...

As long as your underlying type is in fact an int, then this will do the trick.

The Field method does not perform type conversions. If type conversion is required, you should first obtain the column value by using the Field method. The column value should then be converted to another type.

Upvotes: 1

NPayette
NPayette

Reputation: 179

As Dynamy stated you can use the

DateTime? which is a Nullable type of date.

Nullable Type C#

N.

Upvotes: 0

NerdFury
NerdFury

Reputation: 19214

I like to keep this utility class around for dealing with DBNull values

public static class DBNullConvert
{
    public static T To<T>(object value, T defaultValue)
    {
        T cast;

        try
        {
            cast = value == DBNull.Value ? defaultValue : (T)value;
        }
        catch
        {
            throw new ArgumentException(string.Format("Argument of type {0} cannot be cast to type {1}", value.GetType(), typeof(T)), "value");
        }

        return cast;
    }

    public static T To<T>(object value)
    {
        return To(value, default(T));
    }

    public static T? ToNullable<T>(object value) where T : struct
    {
        T? cast;

        try
        {
            cast = value == DBNull.Value ? null : (T?)value;
        }
        catch
        {
            throw new ArgumentException(string.Format("Argument of type {0} cannot be cast to type {1}", value.GetType(), typeof(T?)), "value");
        }

        return cast;
    }

    public static string ToString(object value)
    {
        return To(value, String.Empty);
    }
}

Then you can use it like this:

DBNullConvert.ToNullable<DateTime>(dt.Rows[prjIdx]["ReceivedDate"])

which will return null if the field is DBNull.Value or the datetime stored in the field if there is one.

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

Reputation: 1038940

Change to nullable DateTime.

Upvotes: 0

Related Questions