Проверка наличия столбца в устройстве чтения данных
Есть ли способ увидеть, существует ли поле в объекте на основе IDataReader без проверки исключения IndexOutOfRangeException?
В сущности, у меня есть метод, который принимает объект на основе IDataReader и создает строго типизированный список записей. В 1 случае один считыватель данных имеет поле, которое другие нет. Я не хочу переписывать все запросы, которые подают этот метод, чтобы включить некоторую форму этого поля, если мне это не нужно. Единственный способ, которым я смог выяснить, как это сделать до сих пор, - это бросить 1 уникальное поле в блок try/catch, как показано ниже.
try
{
tmp.OptionalField = reader["optionalfield"].ToString();
}
catch (IndexOutOfRangeException ex)
{
//do nothing
}
Есть ли более чистый способ добавить "необязательное поле" к другим запросам или скопировать метод загрузки, так что 1 версия использует необязательное поле, а другая - нет?
Я тоже в рамках 2.0.
Ответы
Ответ 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);