Поиски на основе порядковых номеров в DataReader против именованных поисков - PullRequest
5 голосов
/ 02 мая 2011

Microsoft (и многие разработчики) утверждают , что метод SqlDataReader.GetOrdinal повышает производительность извлечения значений из DataReader по сравнению с использованием именованных поисков, т.е.Читатель [ "ColumnName"].Вопрос в том, в чем разница в производительности true при работе с небольшими постраничными наборами записей?Стоит ли тратить дополнительные средства на поиск и обращение порядковых индексов по всему коду?

Ответы [ 4 ]

6 голосов
/ 02 мая 2011

Microsoft рекомендует не вызывать GetOrdinal в цикле.

Это может включать косвенные вызовы со строковым индексатором.

Вы можете использовать GetOrdinal в верхней части циклапоместите порядковые числа в массив, и индексы в массиве должны быть константными или иметь перечисление для них (вообще не использовать GetOrdinal) или использовать GetOrdinal для отдельных переменных с описательными именами.

Только если ваши наборы малы,Я действительно считаю, что это преждевременная оптимизация.

Это, очевидно, штраф 3%.

5 голосов
/ 02 мая 2011

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

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

2 голосов
/ 02 мая 2011

Да и нет.

Если вы имеете дело с огромным количеством данных, вам, безусловно, будет полезно использовать порядковые номера, а не имена столбцов.

В противном случае, сделайте его простым, читабельным и несколько более безопасным - и придерживайтесь имен столбцов.

Оптимизируйте только тогда, когда вам нужно.

0 голосов
/ 25 августа 2011

Я создал оболочку для SqlDataReader, которая хранит orindals в словаре с именем столбца в качестве ключа.

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

Friend Class DataReader
Implements IDisposable

Private _reader As SqlDataReader
Private _oridinals As Dictionary(Of String, Integer)
Private Shared _stringComparer As StringComparer = StringComparer.OrdinalIgnoreCase 'Case in-sensitive

Public Sub New(reader As SqlDataReader)
    Me._reader = reader
    Me.SetOrdinals()
End Sub

Private Sub SetOrdinals()
    Me._oridinals = New Dictionary(Of String, Integer)(_stringComparer)
    For i As Integer = 0 To Me._reader.FieldCount - 1
        Me._oridinals.Add(Me._reader.GetName(i), i)
    Next
End Sub

Public Function Read() As Boolean
    Return Me._reader.Read()
End Function

Public Function NextResult() As Boolean
    Dim value = Me._reader.NextResult()
    If value Then
        Me.SetOrdinals()
    End If
    Return value
End Function

Default Public ReadOnly Property Item(name As String) As Object
    Get
        Return Me._reader(Me.GetOrdinal(name))
    End Get
End Property

Public Function GetOrdinal(name As String) As Integer
    Return Me._oridinals.Item(name)
End Function

Public Function GetInteger(name As String) As Integer
    Return Me._reader.GetInt32(Me.GetOrdinal(name))
End Function

Public Function GetString(ordinal As Integer) As String
    Return Me._reader.GetString(ordinal)
End Function

Public Function GetString(name As String) As String
    Return Me._reader.GetString(Me.GetOrdinal(name))
End Function

Public Function GetDate(name As String) As Date
    Return Me._reader.GetDateTime(Me.GetOrdinal(name))
End Function

Public Function GetDateNullable(name As String) As Nullable(Of Date)
    Dim o = Me._reader.GetValue(Me.GetOrdinal(name))
    If o Is System.DBNull.Value Then
        Return Nothing
    Else
        Return CDate(o)
    End If
End Function

Public Function GetDecimal(name As String) As Decimal
    Return Me._reader.GetDecimal(Me.GetOrdinal(name))
End Function

Public Function GetBoolean(name As String) As Boolean
    Return Me._reader.GetBoolean(Me.GetOrdinal(name))
End Function

Public Function GetByteArray(name As String) As Byte()
    Return CType(Me._reader.GetValue(Me.GetOrdinal(name)), Byte())
End Function

Public Function GetBooleanFromYesNo(name As String) As Boolean
    Return Me._reader.GetString(Me.GetOrdinal(name)) = "Y"
End Function

'Disposable Code

End Class
...