SqlDataReader Порядковый номер столбца - PullRequest
2 голосов
/ 28 мая 2009

Предположим, я звоню по запросу "ВЫБЕРИТЕ имя, город, страну ИЗ ЛЮДЕЙ". Когда я выполняю SqlDataReader, столбцы появляются в том же порядке, что и в моем sql-запросе?

Другими словами, могу ли я рассчитывать, что следующий код всегда будет работать правильно:

SqlConnection connection = new SqlConnection(MyConnectionString);
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = "SELECT [name], [city], [country] WHERE [id] = @id";

try
{
    connection.Open();
    SqlDataReader reader = command.ExecuteReader(System.Data.CommandBehavior.SingleRow);

    if (reader.Read())
    {
        // Read values.
        name = reader[0].ToString();
        city = reader[1].ToString();
        country = reader[2].ToString();
    }
}
catch (Exception)
{
    throw;
}
finally
{
    connection.Close();
}

Кроме того, какую производительность я теряю, если вместо ординалов использовать имена столбцов (reader ["name"])?

Существуют ли официальные документы Microsoft, описывающие поведение упорядочения столбцов в SqlDataReader?

Ответы [ 3 ]

5 голосов
/ 28 мая 2009

Я полностью согласен с Джошем - позиции полей действительно такие, как вы указываете их в тексте SQL-запроса.

НО: я бы все же предпочел использовать имена столбцов, так как они более устойчивы. Например. Что делать, если вам нужно добавить поле в ваш запрос SQL?

command.CommandText = "SELECT [name], [jobtitle], [city], [country] WHERE [id] = @id";

Теперь внезапно вам нужно переписать весь код, чтобы изменить позиции ....

Что я обычно делаю вне цикла, который перечисляет все строки, возвращаемые считывателем данных, так это определяет позиции каждого интересующего меня поля:

int namePosition = reader.GetOrdinal("name");
int cityPosition = reader.GetOrdinal("city");

и затем я использую эти позиции внутри своего цикла, обрабатывающего данные, чтобы получить быстрый доступ к отдельным полям. Таким образом, вы определяете позиции только один раз, но вы используете позиции в цикле по данным - лучшее из обоих миров! : -)

Марк

5 голосов
/ 28 мая 2009

Да, это так, но вы также можете использовать SqlDataReader.GetName (порядковый номер) и SqlDataReader.GetOrdinal (имя).

Что касается производительности, я думаю, что она, вероятно, крайне незначительна по сравнению с накладными расходами, скажем, при получении следующей строки данных.

4 голосов
/ 21 июля 2010

Этот пример наиболее понятен и прост для чтения:

int? quantity = reader.Get<int?>("Quantity");
Guid token = reader.Get<Guid>("Token");

Он основан на следующем методе расширения, который я создал. Он выполняет нулевые проверки БД, выдает информационное сообщение об ошибке, когда поле не найдено, и не прерывается, когда столбцы перестраиваются.

internal static T Get<T>(this SqlDataReader reader, string fieldName)
{
    int ordinal;
    try
    {
        ordinal = reader.GetOrdinal(fieldName);
    }
    catch (IndexOutOfRangeException)
    {
        throw new IndexOutOfRangeException(string.Format("Field name '{0}' not found.", fieldName));
    }

    return !reader.IsDBNull(ordinal) ? (T)reader.GetValue(ordinal) : default(T);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...