C# 检查数据读取器中是否存在列

C# 检查数据读取器中是否存在列,c#,idatareader,C#,Idatareader,是否有一种方法可以查看基于IDataReader的对象中是否存在字段,而不只是检查IndexOutOfRangeException 本质上,我有一个方法,它接受一个基于IDataReader的对象并创建一个强类型的记录列表。在1个实例中,一个数据读取器有一个其他读取器没有的字段。如果不需要的话,我真的不想重写为这个方法提供信息的所有查询来包含这个字段的某种形式。到目前为止,我唯一能够弄清楚如何做的方法是将1唯一字段抛出到try/catch块中,如下所示 try { tmp.Optiona

是否有一种方法可以查看基于IDataReader的对象中是否存在字段,而不只是检查IndexOutOfRangeException

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

try
{
    tmp.OptionalField = reader["optionalfield"].ToString();
}
catch (IndexOutOfRangeException ex)
{
    //do nothing
}
除了将“可选字段”添加到其他查询或复制加载方法之外,还有没有更干净的方法使1版本使用可选字段而另一版本不使用


我也在2.0框架中。

看来我的观点是正确的。我知道你的实际列名在那里,但我走错了路。帮我把事情弄清楚了一点,但我还是不确定是否有一种优雅的方式。根据上述链接改编,您可以获得包含以下内容的所有列的列表:

List<string> myCols = new List<string>();
DataTable schema = reader.GetSchemaTable();
foreach (DataRow row in schema.Rows)
{
    myCols.Add(row[schema.Columns["ColumnName"]]);
}
List myCols=new List();
DataTable schema=reader.GetSchemaTable();
foreach(schema.Rows中的数据行)
{
myCols.Add(行[schema.Columns[“ColumnName”]);
}
不幸的是,您似乎只能按索引访问schema.Rows,所以我不确定您是否可以在按名称检查之前先遍历这些行。在这种情况下,您原来的解决方案似乎要优雅得多


注意:我最初的回答建议只通过:reader.GetSchemaTable().Columns[“optionalfield”]检查列的存在性。

我最终使用
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;
}
public bool ColumnExists(IDataReader读取器,字符串columnName)
{
对于(int i=0;i
将其加载到数据表中,然后您可以检查列:

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

不需要这么复杂,只需这样:

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

这应该行得通,试试这个:

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);
            }
        }

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

var cols=reader.GetSchemaTable()
.行
第()类
。选择(行=>行[“ColumnName]”);
或检查列是否存在:

public bool ColumnExists(IDataReader reader, string columnName)
{

  return reader.GetSchemaTable()
               .Rows
               .OfType<DataRow>()
               .Any(row => row["ColumnName"].ToString() == columnName);
}
public bool ColumnExists(IDataReader读取器,字符串columnName)
{
返回reader.GetSchemaTable()
.行
第()类
.Any(row=>row[“ColumnName”].ToString()==ColumnName);
}

在深入研究GetSchemaTable()之后,它似乎得到了完全不同的列元数据,而不是底层表。显示了IsColumnSet和ColumnSize等列,而不是实际字段。我得到的列列表可以在此页面的列表中找到:不幸的是,该上下文中的“列”是关于IDataReader的元数据列,而不是IDataReader的列列表。GetSchemaTable()DataTable中的每一行都是datareader中的一列。如果您不限于.net 2.0,那么您可以这样做:bool bFieldExists=datareader.GetSchemaTable().Columns.Select(o=>o.Name).Contains(myColumnName);它不工作datareader.GetSchemaTable().Columns.Select(o=>o.Name).Contains(myColumnName);这也不行我想知道为什么MS没有将此函数添加到DataReaderyou可以改进if语句:if(reader.GetName(i).Equals(columnName,StringComparison.InvariantCultureIgnoreCase))如果使用别名怎么办?在这种情况下,比较肯定是不正确的?这使用需要.NET 3.5或更高版本的Linq。在OP说他正在使用的.NET 2.0上不起作用。这使用需要.NET 3.5或更高版本的LINQ。操作人员说他正在使用的.NET2.0不起作用。ColumnExists“是一个很好的函数。但是请注意,正如上面所写的,示例代码是不完整的。必须向比较中添加显式转换,否则它将使用引用比较并始终返回false。任意(行=>(字符串)行[“ColumnName”]==ColumnName);
public bool ColumnExists(IDataReader reader, string columnName)
{

  return reader.GetSchemaTable()
               .Rows
               .OfType<DataRow>()
               .Any(row => row["ColumnName"].ToString() == columnName);
}
Enumerable.Range(0, reader.FieldCount).Any(i => reader.GetName(i) == "ColumnName")