2011-05-02 37 views
5

Microsoft(和許多開發人員)claim SqlDataReader.GetOrdinal方法提高了從DataReader中檢索值的性能,而不是使用命名查找的性能。讀取器[ 「的ColumnName」]。問題是如果處理小的分頁記錄集,那麼性能差異是什麼true?是否值得在代碼中查找和引用序號索引的額外開銷?DataReader基於序號的查找與命名查詢

+0

一些基準:http://blog.maskalik.com/ado-net/data-reader-performance-optimizations/ – nawfal 2015-07-31 14:29:53

回答

5

Microsoft recommends not calling GetOrdinal within a loop.

這將包括與字符串索引間接調用。

您可以在循環的頂部使用GetOrdinal,將序數放在數組中,並使數組中的索引爲常量,或者爲它們設置枚舉(根本不使用GetOrdinal),或者將GetOrdinal用於具有描述性名稱的單個變量。

只有當你的設置很小時,我纔會認爲這是過早的優化。

It's apparently a 3% penalty.

2

是和否。

如果你正在處理大量的數據,那麼你肯定會從使用序號而不是列名獲益。

否則,請保持簡單,可讀,有些安全 - 並堅持使用列名稱。

僅在需要時進行優化。

+1

「可讀的,有些更安全 - 並堅持與列名」我要說的是,是序數提供的。你可以給你的序號一個不錯的名字'int ordinalUserName = reader.GetOrdinal(「user_name」)'所以它也是可讀的。如果你在一個地方聲明所有的序號,而不是在某個邏輯中分散列名,它也可以被認爲更可讀和更安全。 – row1 2014-03-21 05:06:13

3

任何差異將比維護開銷壓倒了。

如果你有這麼多的數據,它會產生明顯的差異,我建議你的客戶端代碼中有太多的數據。或者這是當你考慮使用序號而不是名稱

-1

我創建了一個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 
+1

是不是SqlDataReader已經有一個字典作爲其GetOrdinal()實現的一部分?你是否真的測量過Item [string]的任何性能改進? – binki 2013-09-17 17:24:56