tags:

views:

609

answers:

4

Is there a way to see if a field exists in an IDataReader-based object w/o just checking for an IndexOutOfRangeException?

In essence, I have a method that takes an IDataReader-based object and creates a strongly-typed list of the records. In 1 instance, one data reader has a field that others do not. I don't really want to rewrite all of the queries that feed this method to include some form of this field if I don't have to. The only way I have been able to figure out how to do it so far is to throw the 1 unique field into a try/catch block as shown below.

try
{
    tmp.OptionalField = reader["optionalfield"].ToString();
}
catch (IndexOutOfRangeException ex)
{
    //do nothing
}

Is there a cleaner way short of adding the "optional field" to the other queries or copying the loading method so 1 version uses the optional field and the other doesn't?

I'm in the 2.0 framework also.

+3  A: 

Appears I stand corrected. I know your actual column names are in there, but I was going down the wrong path. This reference helped clear things up a bit, but I'm still not sure if there's an elegant way of doing it. Adapted from the above link, you could get a list of all of your columns with the following:

List<string> myCols = new List<string>();
DataTable schema = reader.GetSchemaTable();
foreach (DataRow row in schema.Rows)
{
    myCols.Add(row[schema.Columns["ColumnName"]]);
}

Unfortunately it appears you can only access schema.Rows by index, so I'm not sure you can get around looping through the rows first before checking by name. In that case, your original solution seems far more elegant!

Note: my original answer suggested checking for presence of a column simply by: reader.GetSchemaTable().Columns["optionalfield"].

Kurt Schindler
After looking deeper into GetSchemaTable(), it appears to get completely different column metadata and not the underlying table. Columns like IsColumnSet and ColumnSize are presented and not the actual fields.
JamesEggers
A list of the columns I'm getting can be found in the list on this page:http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.getschematable%28VS.80%29.aspx
JamesEggers
+1  A: 

I ended up finding a solution using the reader.GetName(int) method. I created the below method to encompass the logic.

public bool ColumnExists(IDataReader reader, string columnName)
{
    for (int i = 0; i < reader.FieldCount; i++)
    {
        if (reader.GetName(i) == columnName)
        {
            return true;
        }
    }

    return false;
}
JamesEggers
A: 

Load it into a DataTable and then you can check for column:

DataTable dataTable = new DataTable();
dataTable.Load(reader);
foreach (var item in dataTable.Rows) 
{
    bool columnExists = item.Table.Columns.Contains("ColumnName");
}
Seb Nilsson
+2  A: 

Don't need so much complication, just this:

bool bFieldExists = datareader.GetSchemaTable().Columns.Contains(strFieldName);

Regards,

Asdrubal

Asdrubal
Unfortunately the "Columns" in that context are the columns of metadata about The IDataReader, not the IDataReader's list of columns. Each row within the GetSchemaTable() DataTable is a column in datareader.
JMD