如何使用相同的代码从 DataRow 或 DataReader 中读取数据?
Posted
技术标签:
【中文标题】如何使用相同的代码从 DataRow 或 DataReader 中读取数据?【英文标题】:How can I read from a DataRow or a DataReader using the same code? 【发布时间】:2011-10-05 19:53:56 【问题描述】:目前,我正在使用一个加载了简单数据库“选择”查询的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
我写的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
在某些情况下,我必须从DataRow
而不是SqlDataReader
读取数据。但代码将完全相同!当我查看我的GetItemFromData
方法时,我想在dr
参数中接受更通用的对象类型,这样我就可以将DataReader
与DataRow
一样对待,因为我将编写确切的如果我编写了一个打算使用DataRow
的方法,那么方法中的相同代码。有没有办法做到这一点?
【问题讨论】:
【参考方案1】:我能想到的唯一方法是包装一些类并实现一个接口 - 类似于:
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
然后,您必须先包装您的行或阅读器,然后再将其传递给您的方法:
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))
【讨论】:
这本质上是包装两个对象的适配器模式。我会注意到SqlDataReader
实现了IDataReader
,它公开了Item
属性。不幸的是,DataRow
没有实现相同的接口,尽管它公开了相同的功能。在这种情况下,使用适配器模式仅适应DataRow
(class DataRowAdapter : IDataReader
),然后让方法接受IDataReader
可能是一种可行的做法。
DataRow 没有实现 IDataRecord 是 bcl 中的一个可悲的错误:(
@AnthonyPegram 有道理,但是 IDataReader 中有大量的属性和方法,所以除了实现的一个属性之外,你必须有一堆 NotImplementedException
或类似的属性(或实际实现它们,如果您只关心索引器,这似乎不合适)。
@Joe - 你只能在 IDataRecord 上构建你的包装器,它几乎没有太多的实现。
@AnthonyPegram @JoelCoehoorn 同意 - DataRow
绝对应该实现 IDataRecord
。我想知道是否有任何原因,或者这只是一个尚未修复的疏忽。【参考方案2】:
改用DataTable
怎么样:
Dim DataTable table AS new DataTable()
table.Load(GetItemsDataReader())
foreach (DataRow row in table.Rows)
Dim item As Item = GetItemFromData(row)
loadedItems.Add(item)
将您的 GetItemFromData() 方法更改为采用 DataRow
而不是 DataReader
(对于 VB.NET/C# 混合伪代码感到抱歉)。
【讨论】:
这可能行得通,但我觉得这是朝着错误方向迈出的一步。以上是关于如何使用相同的代码从 DataRow 或 DataReader 中读取数据?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 DataGridView 中的一行获取 DataRow
Powershell 连接变量导致 System.Data.DataRow