Duarte Patrício
Duarte Patrício

Reputation: 143

C# - don't break a try catch block

I want to set values that I read from a database to strings (using a SqlDataReader). I have a try-catch block to catch some System.DBNull that may come from the database table. And whenever those nulls appear I want to set a different value to that field. Those fields are then to be set to an object and then added to a list.

The following code demostrates better my problem:

while (reader.Read())
{
    try
    {
        string originalfilename = (string)reader[0];
        string renamedfilename = (string)reader[1];
        string sheet = (string)reader[2];
        string version = (string)reader[3];

        AddDocument(originalfilename, renamedfilename, sheet, version);
    }
    catch (InvalidCastException e)
    {
        e.Source = "N/A";
    }
}

In the example, if reader[2] is System.DBNull then I want that the sheet string to have "N/A", but I want version to be set normally from reader[3] and AddDocument executed after.

I am looking for a solution without many if's. I thought that e.Source would solve my problem but the try block breaks after the exception is caught.

Thank you in advance.

Upvotes: 0

Views: 3543

Answers (4)

paparazzo
paparazzo

Reputation: 45096

I think the ?: operator is the most direct approach.

while (reader.Read())
{
    string originalfilename = reader.GetString(0);
    string renamedfilename = (string)reader[1];
    string sheet = rdr.IsDBNull(2) ? "N/A" : reader.GetString(2);;
    string version = (string)reader[3];
    AddDocument(originalfilename, renamedfilename, sheet, version);
}

to be safe (and simple)

while (reader.Read())
{
    AddDocument(rdr.IsDBNull(0) ? "N/A" : reader.GetString(0)
               ,rdr.IsDBNull(1) ? "N/A" : reader.GetString(1)
               ,rdr.IsDBNull(2) ? "N/A" : reader.GetString(2)
               ,rdr.IsDBNull(3) ? "N/A" : reader.GetString(3));
}

Upvotes: 0

Postlagerkarte
Postlagerkarte

Reputation: 7117

Simple approach:

var sheet = reader[2] as string ?? "N/A"

or use an extension method:

    public static class DataReaderExtensions 
    {
        public static T Read<T>(this SqlDataReader reader, int index, T defaultValue = default(T))
        {
            var value = reader[index];

            return (T)((DBNull.Value.Equals(value))
                       ? defaultValue
                       : Convert.ChangeType(value, typeof(T)));
        }
    }

and use it like that:

while(myDataReader.Read())
{
  string sheet = myDataReader.Read<string>(2, "n/a");
}

Upvotes: 2

brz
brz

Reputation: 6016

You shouldn't use exceptions like this, exceptions are for exceptional circumstances. You have to define a method that returns a default value if it's parameter is DbNull:

private T GetValueOrDefault<T>(object val, T defaultValue)
{
    if(val == DBNull.Value)
        return defaultValue;
    return (T)val;
}

Then you can use this method like this:

while (reader.Read())
{
    string originalfilename = GetValueOrDefault<string>(reader[0], "N/A");
    string renamedfilename = GetValueOrDefault<string>(reader[1], "N/A");
    string sheet = GetValueOrDefault<string>(reader[2], "N/A");
    string version = GetValueOrDefault<string>(reader[3], "N/A");

    AddDocument(originalfilename, renamedfilename, sheet, version);
}

Upvotes: 2

Tim Schmelter
Tim Schmelter

Reputation: 460118

Don't use try-catch for normal work-flow, instead you should use reader.IsDBNull:

string originalfilename = reader.GetString(0);
string renamedfilename = reader.GetString(1)
string sheet = null;
if(reader.IsDBNull(2))
    sheet = "N/A";
else
     sheet = reader.GetString(2);
string version = reader.GetString(3)

Upvotes: 1

Related Questions