如何使用相同的代码从DataRow或DataReader读取?

Bra*_*ery 1 .net datareader datarow

目前,我正在使用一个SqlDataReader简单的数据库"选择"查询.每行代表一个域对象,所以我像这样膨胀每个对象:

Dim loadedItems As New List(Of Item)
Dim dr As SqlDataReader = GetItemsDataReader()
While dr.Read()
  Dim item As Item = GetItemFromData(dr)
  loadedItems.Add(item)
End While
Run Code Online (Sandbox Code Playgroud)

GetItemFromData我写的方法看起来像这样:

Private Function GetItemFromData(dr As SqlDataReader) As Item
  Dim loadedItem As New Item()
  loadedItem.ID = dr("ID")
  loadedItem.Name = dr("Name")
  'etc., etc.'
  Return loadedItem
End Function
Run Code Online (Sandbox Code Playgroud)

在某些情况下,我必须从a DataRow而不是a 读取数据SqlDataReader.但代码将完全相同!当我查看我的GetItemFromData方法时,我想在dr参数中接受一个更通用的对象类型,这样我就可以DataReader像a一样对待它DataRow,因为如果我写的是一个意思,我会在方法中编写完全相同的代码用一个DataRow.有没有办法做到这一点?

Joe*_*nos 5

我能想到的最好的方法就是包装几个类并实现一个表面 - 例如:

Interface IIndexer
    Default ReadOnly Property Item(ByVal index As String)
End Interface

Class DataReaderWrapper
    Implements IIndexer

    Private ReadOnly _reader As IDataReader

    Public Sub New(reader As IDataReader)
        _reader = reader
    End Sub

    Public ReadOnly Property Item(index As String) As Object Implements IIndexer.Item
        Get
            Return _reader(index)
        End Get
    End Property
End Class

Class DataRowWrapper
    Implements IIndexer

    Private ReadOnly _row As DataRow

    Public Sub New(row As DataRow)
        _row = row
    End Sub

    Public ReadOnly Property Item(index As String) As Object Implements IIndexer.Item
        Get
            Return _row(index)
        End Get
    End Property
End Class
Run Code Online (Sandbox Code Playgroud)

然后,在将行或读取器传递给方法之前,必须将其包装起来:

Private Function GetItemFromData(indexer As IIndexer) As Item
    Dim loadedItem As New Item()
    loadedItem.ID = indexer("ID")
    loadedItem.Name = indexer("Name")
    'etc., etc.'
    Return loadedItem
End Function

Dim i As Item = GetItemFromData(New DataRowWrapper(dr))
Run Code Online (Sandbox Code Playgroud)

  • 这实际上是包装两个对象的适配器模式.我将注意到`SqlDataReader`实现了`IDataReader`,它暴露了`Item`属性.不幸的是,`DataRow`没有实现这个相同的接口,尽管它暴露了相同的功能.在这种情况下,使用适配器模式来适应*只是*DataRow`(`类DataRowAdapter:IDataReader`),然后让方法接受`IDataReader`可能是一个可行的行动方案. (4认同)
  • 那个DataRow没有实现IDataRecord是bcl中的一个可悲的错误:( (4认同)
  • @AnthonyPegram有道理,但IDataReader中有很多属性和方法,所以除了实现的一个属性之外,你必须有一堆`NotImplementedException`或类似的东西(或者实际实现它们,它们没有'如果你关心的只是索引器,那似乎是合适的. (2认同)