Подтвердить что ты не робот

Проверка наличия столбца в устройстве чтения данных

Есть ли способ увидеть, существует ли поле в объекте на основе IDataReader без проверки исключения IndexOutOfRangeException?

В сущности, у меня есть метод, который принимает объект на основе IDataReader и создает строго типизированный список записей. В 1 случае один считыватель данных имеет поле, которое другие нет. Я не хочу переписывать все запросы, которые подают этот метод, чтобы включить некоторую форму этого поля, если мне это не нужно. Единственный способ, которым я смог выяснить, как это сделать до сих пор, - это бросить 1 уникальное поле в блок try/catch, как показано ниже.

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

Есть ли более чистый способ добавить "необязательное поле" к другим запросам или скопировать метод загрузки, так что 1 версия использует необязательное поле, а другая - нет?

Я тоже в рамках 2.0.

4b9b3361

Ответ 1

В итоге я нашел решение, используя метод 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;
}

Ответ 2

Следующее предоставит вам список строк с именами столбцов, заданных считывателем данных. (Помните, что результаты основаны на последнем чтении, поэтому может быть не так, в зависимости от того, что читатель читает).

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

Ответ 3

Появляется, я исправляюсь. Я знаю, что ваши фактические имена столбцов находятся там, но я шел по неправильному пути. Эта ссылка помогла мне немного разобраться, но я все еще не уверен, есть ли элегантный способ сделать это. Адаптированный из приведенной выше ссылки, вы можете получить список всех ваших столбцов со следующим:

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(). Столбцы [ "необязательное поле" ].

Ответ 4

Enumerable.Range(0, reader.FieldCount).Any(i => reader.GetName(i) == "ColumnName")

Ответ 5

Это должно работать, попробуйте следующее:

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

Ответ 6

Загрузите его в DataTable, а затем вы можете проверить наличие столбца:

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

Ответ 7

Не нужно так много усложнений, просто это:

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