IDataReader и "HasColumn", лучший подход? - PullRequest
6 голосов
/ 10 января 2009

Я видел два распространенных подхода к проверке, существует ли столбец в IDataReader:

public bool HasColumn(IDataReader reader, string columnName)
{
  try
  {
      reader.getOrdinal(columnName)
      return true;
  }
  catch 
  {
       return false;
  }
}

Или:

public bool HasColumn(IDataReader reader, string columnName)
{

    reader.GetSchemaTable()
         .DefaultView.RowFilter = "ColumnName='" + columnName + "'";

    return (reader.GetSchemaTable().DefaultView.Count > 0);
}

Лично я использовал второй, так как ненавижу использовать исключения по этой причине.

Однако в большом наборе данных я считаю, что RowFilter, возможно, придется выполнять сканирование таблицы по столбцу, а это может быть невероятно медленным.

Мысли

Ответы [ 3 ]

5 голосов
/ 14 июля 2009

Думаю, у меня есть разумный ответ на этот старый камень.

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

public Dictionary<string,int> CacheFields(IDataReader reader)
{

    var cache = new Dictionary<string,int>();
    for (int i = 0; i < reader.FieldCount; i++)
    {
        cache[reader.GetName(i)] = i;
    }
    return cache;
}

Преимущество этого подхода в том, что он проще и дает вам лучший контроль. Кроме того, обратите внимание, что вы можете захотеть взглянуть на сравнение без учета регистра или без учета kana, что может усложнить задачу.

1 голос
/ 10 января 2009

Многое зависит от того, как вы используете HasColumn. Вы называете это только один или два раза, или несколько раз в цикле? Вероятно, колонна там или заранее неизвестна?

Установка фильтра строк, вероятно, будет выполнять сканирование таблицы каждый раз. (Кроме того, теоретически, GetSchemaTable () может генерировать совершенно новую таблицу с каждым вызовом, что будет еще дороже - я не верю, что SqlDataReader делает это, но на уровне IDataReader, кто знает?) Но если вы только Назовите это один или два раза, я не могу представить, что это большая проблема (если у вас нет тысяч столбцов или чего-то в этом роде).

(Однако я бы, по крайней мере, сохранил результат GetSchemaTable () в локальной переменной внутри метода, чтобы не вызывать его дважды в быстрой последовательности, если не кэшировать его где-то, если ваш конкретный IDataReader действительно его регенерирует) .)

Если вы заранее знаете, что при нормальных обстоятельствах столбец, который вы запрашиваете, будет присутствовать, метод исключения будет более приемлемым (поскольку столбец, который там не существует, фактически является исключительным случаем). Даже если это не так, он может работать немного лучше, но, если вы не будете повторять его, вы должны спросить себя, действительно ли производительность вызывает такое большое беспокойство.

И если вы вызываете его неоднократно, вам, вероятно, следует в любом случае рассмотреть другой подход, например: вызвать GetSchemaTable () один раз, выполнить цикл по таблице и загрузить имена полей в словарь или какую-либо другую структуру, предназначен для быстрого поиска.

0 голосов
/ 22 мая 2009

Я бы не беспокоился о влиянии на производительность. Даже если у вас была таблица с 1000 столбцами (что было бы огромной таблицей), вы все равно выполняете «сканирование таблицы» из 1000 строк. Это может быть тривиальным.

Преждевременная оптимизация просто приведет вас к излишне сложной реализации. Реализуйте версию, которая кажется вам наиболее подходящей, и затем измерьте влияние на производительность. Если это неприемлемо по сравнению с вашими требованиями к производительности, рассмотрите альтернативы.

...