49

有没有办法查看一个字段是否存在于基于 IDataReader 的对象中,而无需检查 IndexOutOfRangeException?

本质上,我有一个方法,它接受一个基于 IDataReader 的对象并创建一个强类型的记录列表。在一种情况下,一个数据读取器具有其他人没有的字段。如果我不需要的话,我真的不想重写所有提供此方法的查询以包含该字段的某种形式。到目前为止,我能够弄清楚如何做到这一点的唯一方法是将 1 个唯一字段放入 try/catch 块中,如下所示。

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

除了将“可选字段”添加到其他查询或复制加载方法以使 1 个版本使用可选字段而另一个不使用之外,是否有更简洁的方法?

我也在2.0框架中。

4

7 回答 7

64

我最终找到了使用该reader.GetName(int)方法的解决方案。我创建了以下方法来包含逻辑。

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

    return false;
}
于 2009-07-31T16:03:00.763 回答
21

下面将为您提供给定数据阅读器的列名字符串列表。(请记住,结果基于最后一次阅读,因此根据读者阅读的内容可能会有所不同)。

var cols = reader.GetSchemaTable()
                 .Rows
                 .OfType<DataRow>()
                 .Select(row => row["ColumnName"]);

或者检查列是否存在:

public bool ColumnExists(IDataReader reader, string columnName)
{

  return reader.GetSchemaTable()
               .Rows
               .OfType<DataRow>()
               .Any(row => row["ColumnName"].ToString() == columnName);
}
于 2012-07-12T21:48:53.463 回答
10
Enumerable.Range(0, reader.FieldCount).Any(i => reader.GetName(i) == "ColumnName")
于 2014-03-13T01:00:39.217 回答
7

这应该工作,试试这个:

private static bool ColumnExists(SqlDataReader reader, string columnName)
        {
            using (var schemaTable = reader.GetSchemaTable())
            {
                if (schemaTable != null)
                    schemaTable.DefaultView.RowFilter = String.Format("ColumnName= '{0}'", columnName);

                return schemaTable != null && (schemaTable.DefaultView.Count > 0);
            }
        }
于 2011-10-13T09:56:52.320 回答
6

看来我的立场是正确的。我知道你的实际列名在那里,但我走错了路。这个参考有助于澄清一些事情,但我仍然不确定是否有一种优雅的方式来做到这一点。改编自上面的链接,您可以获得所有列的列表,其中包含以下内容:

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

不幸的是,您似乎只能按索引访问 schema.Rows,因此我不确定您是否可以先遍历行,然后再按名称检查。在这种情况下,您的原始解决方案似乎更加优雅!

注意:我的原始答案建议通过以下方式检查列是否存在:reader.GetSchemaTable().Columns["optionalfield"]。

于 2009-07-30T13:30:53.547 回答
3

将其加载到 DataTable 中,然后您可以检查列:

DataTable dataTable = new DataTable();
dataTable.Load(reader);
foreach (var item in dataTable.Rows) 
{
    bool columnExists = item.Table.Columns.Contains("ColumnName");
}
于 2009-08-13T13:34:44.720 回答
1

不需要这么复杂,就是这样:

bool bFieldExists = datareader.GetSchemaTable().Columns.Contains(strFieldName);
于 2009-09-02T12:45:20.897 回答