.NET SqlDataReader Item [] и GetString (GetOrdinal ())? - PullRequest
13 голосов
/ 16 мая 2011

Используя класс SqlDataReader, каковы функциональные различия между

(string) dataReader["MyFieldName"];

и

dataReader.GetString(dataReader.GetOrdinal("MyFieldName"));

Ответы [ 5 ]

14 голосов
/ 16 мая 2011

Отбрасывание вопросов в сторону, для единственного вызова их нет. Индексатор вызовет DbDataReader.GetOrdinal, а затем вызовет соответствующий метод Get, чтобы получить значение (обратите внимание, что быстрее вызывать методы Get с использованием порядкового номера, чем использовать индексатор с именем поля).

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

Вы можете сделать это так:

// Move to the first record.  If no records, get out.
if (!dataReader.Read()) return;

// Before the loop.  Can do this for any other fields being
// accessed in the loop as well.
int myFieldNameOrdinal = dataReader.GetOrdinal("MyFieldName");

// Process the records.  Remember, already on the first record, so
// use do/while here.
do
{
    // Do something with your field.
    Console.WriteLine(dataReader.GetString(myFieldNameOrdinal));
} while (dataReader.Read());
3 голосов
/ 16 мая 2011

При работе с нулевым значением:

// Will throw an InvalidCastException 
// Exception Message will be "Unable to cast object of type System.DBNull
// to System.String 
(string) dataReader["MyFieldName"]; 

// Will throw a SqlNullValueException
// Exception Message will be "Data is Null. This method or property
// cannot be called on Null values."
dataReader.GetString(dataReader.GetOrdinal("MyFieldName"));
2 голосов
/ 16 мая 2011

В первом случае вы применяете кастинг, что особенно уродливо для типов значений (включая распаковку). Лично я всегда использую второе, и это то, что я бы порекомендовал вам.

1 голос
/ 14 ноября 2013
//Well, we want to avoid the null exception issue entirely.
//Let's check for null first, before we try to use the value.

if( !dataReader.IsDBNull(dataReader.GetOrdinal("MyFieldName")))
{
//Store my data or use the value
string mystring=dataReader.GetString(dataReader.GetOrdinal("MyFieldName"));
}

Serendipity - замечательный метод открытия.

0 голосов
/ 22 февраля 2015

В качестве альтернативы ответу от casperOne было бы легко уменьшить порядковые поиски, которые будут выполняться один раз за время существования приложения. Это также может быть сделано без необходимости вручную поддерживать переменные для записи каждого из индексов.

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

Начните с поля:

static readonly ConcurrentDictionary<string, int> OrdinalMap = 
            new ConcurrentDictionary<string, int>();

Затем обновите свой код доступа, например:

reader.GetString(OrdinalMap.GetOrAdd("MyFieldName", reader.GetOrdinal))

Теперь у вас есть потокобезопасный O (1) поиск ординалов без необходимости поддерживать какие-либо ручные карты переменных или констант использования, которые, если вы измените запрос, разрушат мир. Не то чтобы это имело значение, но просто для ясности из-за поведения GetOrAdd, если вы выполняете много запросов одновременно, возможно, что reader.GetOrdinal("MyFieldName") может выполняться несколько раз, а не точно один раз, но для всех намерений и целей это может рассматривается как один раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...