DataReader 基于序数的查找与命名查找

发布于 2024-11-04 18:55:03 字数 290 浏览 2 评论 0原文

Microsoft(以及许多开发人员)声明与使用命名查找相比,SqlDataReader.GetOrdinal 方法提高了从 DataReader 检索值的性能。读者[“列名”]。问题是,如果处理小型分页记录集,真实性能差异是什么?在整个代码中查找和引用序数索引是否值得花费额外的开销?

Microsoft (and many developers) claim that the SqlDataReader.GetOrdinal method improves the performance of retrieving values from a DataReader versus using named lookups ie. reader["ColumnName"]. The question is what is the true performance difference if dealing with small, paged record sets? Is it worth the extra overhead of finding and referencing ordinal indexes throughout the code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

烛影斜 2024-11-11 18:55:03

Microsoft 建议不要在循环内调用 GetOrdinal。

这包括使用字符串索引器间接调用。

您可以在循环顶部使用 GetOrdinal 将序号放入数组中,并使数组中的索引为 const 或为它们提供一个枚举(根本没有 GetOrdinal),或者使用 GetOrdinal 到具有描述性名称的各个变量中。

只有当你的集合很小时,我才会真正认为这是不成熟的优化。

这显然是 3 % 惩罚。

Microsoft recommends not calling GetOrdinal within a loop.

That would include indirect calls with the string indexer.

You can use GetOrdinal at the top of your loop put the ordinals in an array and have the indexes in the array be const or have an enum for them (no GetOrdinal at all) or use GetOrdinal into individual variables with descriptive names.

Only if your sets are small would I really consider this to be premature optimization.

It's apparently a 3% penalty.

对你而言 2024-11-11 18:55:03

任何差异都会被维护开销所抵消。

如果您拥有如此多的数据以至于会产生明显的差异,我建议您的客户端代码中的数据过多。或者当您考虑使用序数而不是名称时

Any difference will be more than outweighed by maintenance overhead.

If you have that much data that it makes a noticeable difference, I'd suggest you have too much data in your client code. Or this is when you consider use ordinals rather than names

属性 2024-11-11 18:55:03

是的,也不是。

如果您正在处理大量数据,那么使用序数而不是列名肯定会让您受益匪浅。

否则,请保持简单、可读且更安全——并坚持使用列名称。

仅在需要时进行优化。

Yes and no.

If you're dealing with a massive amount of data then you'd certainly benefit from using the ordinals rather than the column names.

Otherwise, keep it simple, readable, and somewhat safer - and stick with the column names.

Optimize only when you need to.

用心笑 2024-11-11 18:55:03

我为 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

I created a wrapper for SqlDataReader that stores orindals in a dictionary with the column name as the key.

It gives me ordinal performance gains while keeping the code more readable and less likely to break if someone changes the column order returned from stored procedures.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文