通用数据读取器代码(.net)的示例
由于我在.Net方面的经验实际上是从为一家公司开发现有的内部应用程序开始的,因此我觉得我在没有意识到的情况下,发现了很多糟糕的编码实践。我拼命想摆脱的一个问题是,数据集用于一切。我确实知道强类型数据集有其存在的地方,它们当然有一些用途……但不是在大多数情况下,例如选择数据 我正在为泛型数据库工作构建一个helper类…我有一个方法可以返回一个数据表,用于选择等。我猜默认情况下,books/online中的大多数示例都会使用DataAdapter的Fill方法,但肯定是作为性能增益,我想用一个读取所有行然后关闭的数据读取器来代替它…我想这就是Fill方法在下面的工作方式…但是如果大型结果集上的性能可能会受到影响,我不想简单地采用懒惰的方式 无论如何,我一生都找不到一个dataReader被用来一般填充datatable的例子……我确信会有好的和坏的例子,因此在如何执行这样的任务方面会有一个一致的最佳实践。一个链接,甚至一篇文章到这样的代码将是辉煌的!我主要是VB.Net,但c不是障碍通用数据读取器代码(.net)的示例,.net,datareader,.net,Datareader,由于我在.Net方面的经验实际上是从为一家公司开发现有的内部应用程序开始的,因此我觉得我在没有意识到的情况下,发现了很多糟糕的编码实践。我拼命想摆脱的一个问题是,数据集用于一切。我确实知道强类型数据集有其存在的地方,它们当然有一些用途……但不是在大多数情况下,例如选择数据 我正在为泛型数据库工作构建一个helper类…我有一个方法可以返回一个数据表,用于选择等。我猜默认情况下,books/online中的大多数示例都会使用DataAdapter的Fill方法,但肯定是作为性能增益,我想用一个读取
注意:如果这听起来也很懒,很抱歉,我只是想这类例子会被张贴在任何地方…不需要重新发明轮子等。谢谢 找不到DataReader用于一般填充DataTable的示例的原因是,您可以使用数据集中的fill方法执行相同的操作,因此您只是在重新发明轮子
通过直接使用DataReader填充DataTable,您不会发现性能方面的好处。您找不到DataReader用于一般填充DataTable的示例的原因是,您可以使用数据集中的fill方法执行相同的操作,因此您只是在重新发明轮子
通过直接使用DataReader填充DataTable,您不会发现性能优势。如果我不得不猜测,与使用带有fill方法的sqldataadapter相比,使用sqldatareader填充DataTable不会有任何性能优势 真正验证该理论的唯一方法是编写自己的实现并进行比较。但您也可以查看Fill正在执行的代码,以了解它到底在做什么。我建议下载看看代码 这是我自己做的。以下是您打电话填充后最终调用的内容:
Protected Overridable Function Fill(ByVal dataTables As DataTable(), ByVal dataReader As IDataReader, ByVal startRecord As Integer, ByVal maxRecords As Integer) As Integer
Dim num3 As Integer
Dim ptr As IntPtr
Bid.ScopeEnter(ptr, "<comm.DataAdapter.Fill|API> %d#, dataTables[], dataReader, startRecord, maxRecords" & ChrW(10), Me.ObjectID)
Try
ADP.CheckArgumentLength(dataTables, "tables")
If (((dataTables Is Nothing) OrElse (dataTables.Length = 0)) OrElse (dataTables(0) Is Nothing)) Then
Throw ADP.FillRequires("dataTable")
End If
If (dataReader Is Nothing) Then
Throw ADP.FillRequires("dataReader")
End If
If ((1 < dataTables.Length) AndAlso ((startRecord <> 0) OrElse (maxRecords <> 0))) Then
Throw ADP.NotSupported
End If
Dim num2 As Integer = 0
Dim enforceConstraints As Boolean = False
Dim dataSet As DataSet = dataTables(0).DataSet
Try
If (Not dataSet Is Nothing) Then
enforceConstraints = dataSet.EnforceConstraints
dataSet.EnforceConstraints = False
End If
Dim i As Integer
For i = 0 To dataTables.Length - 1
If dataReader.IsClosed Then
goto Label_00DE
End If
Dim container As DataReaderContainer = DataReaderContainer.Create(dataReader, Me.ReturnProviderSpecificTypes)
If (container.FieldCount > 0) Then
If ((0 < i) AndAlso Not Me.FillNextResult(container)) Then
goto Label_00DE
End If
Dim num4 As Integer = Me.FillFromReader(Nothing, dataTables(i), Nothing, container, startRecord, maxRecords, Nothing, Nothing)
If (i = 0) Then
num2 = num4
End If
End If
Next i
Catch exception1 As ConstraintException
enforceConstraints = False
Throw
Finally
If enforceConstraints Then
dataSet.EnforceConstraints = True
End If
End Try
Label_00DE:
num3 = num2
Finally
Bid.ScopeLeave((ptr))
End Try
Return num3
End Function
您会注意到,这会调用FillFromReader:
Friend Function FillFromReader(ByVal dataset As DataSet, ByVal datatable As DataTable, ByVal srcTable As String, ByVal dataReader As DataReaderContainer, ByVal startRecord As Integer, ByVal maxRecords As Integer, ByVal parentChapterColumn As DataColumn, ByVal parentChapterValue As Object) As Integer
Dim num2 As Integer = 0
Dim schemaCount As Integer = 0
Do
If (0 < dataReader.FieldCount) Then
Dim mapping As SchemaMapping = Me.FillMapping(dataset, datatable, srcTable, dataReader, schemaCount, parentChapterColumn, parentChapterValue)
schemaCount += 1
If (((Not mapping Is Nothing) AndAlso (Not mapping.DataValues Is Nothing)) AndAlso (Not mapping.DataTable Is Nothing)) Then
mapping.DataTable.BeginLoadData
Try
If ((1 = schemaCount) AndAlso ((0 < startRecord) OrElse (0 < maxRecords))) Then
num2 = Me.FillLoadDataRowChunk(mapping, startRecord, maxRecords)
Else
Dim num3 As Integer = Me.FillLoadDataRow(mapping)
If (1 = schemaCount) Then
num2 = num3
End If
End If
Finally
mapping.DataTable.EndLoadData
End Try
If (Not datatable Is Nothing) Then
Return num2
End If
End If
End If
Loop While Me.FillNextResult(dataReader)
Return num2
End Function
看了这一切之后,我可能不得不改变主意。为所有这些编写您自己的实现可能确实有一个可测量的改进。这些函数中的逻辑比我预期的要多,并且在反复调用FillNextResult时会产生一些函数调用开销。如果我不得不猜测,与使用带有fill方法的sqldataadapter相比,使用sqldatareader填充数据表不会有任何性能优势 真正验证该理论的唯一方法是编写自己的实现并进行比较。但您也可以查看Fill正在执行的代码,以了解它到底在做什么。我建议下载看看代码 这是我自己做的。以下是您打电话填充后最终调用的内容:
Protected Overridable Function Fill(ByVal dataTables As DataTable(), ByVal dataReader As IDataReader, ByVal startRecord As Integer, ByVal maxRecords As Integer) As Integer
Dim num3 As Integer
Dim ptr As IntPtr
Bid.ScopeEnter(ptr, "<comm.DataAdapter.Fill|API> %d#, dataTables[], dataReader, startRecord, maxRecords" & ChrW(10), Me.ObjectID)
Try
ADP.CheckArgumentLength(dataTables, "tables")
If (((dataTables Is Nothing) OrElse (dataTables.Length = 0)) OrElse (dataTables(0) Is Nothing)) Then
Throw ADP.FillRequires("dataTable")
End If
If (dataReader Is Nothing) Then
Throw ADP.FillRequires("dataReader")
End If
If ((1 < dataTables.Length) AndAlso ((startRecord <> 0) OrElse (maxRecords <> 0))) Then
Throw ADP.NotSupported
End If
Dim num2 As Integer = 0
Dim enforceConstraints As Boolean = False
Dim dataSet As DataSet = dataTables(0).DataSet
Try
If (Not dataSet Is Nothing) Then
enforceConstraints = dataSet.EnforceConstraints
dataSet.EnforceConstraints = False
End If
Dim i As Integer
For i = 0 To dataTables.Length - 1
If dataReader.IsClosed Then
goto Label_00DE
End If
Dim container As DataReaderContainer = DataReaderContainer.Create(dataReader, Me.ReturnProviderSpecificTypes)
If (container.FieldCount > 0) Then
If ((0 < i) AndAlso Not Me.FillNextResult(container)) Then
goto Label_00DE
End If
Dim num4 As Integer = Me.FillFromReader(Nothing, dataTables(i), Nothing, container, startRecord, maxRecords, Nothing, Nothing)
If (i = 0) Then
num2 = num4
End If
End If
Next i
Catch exception1 As ConstraintException
enforceConstraints = False
Throw
Finally
If enforceConstraints Then
dataSet.EnforceConstraints = True
End If
End Try
Label_00DE:
num3 = num2
Finally
Bid.ScopeLeave((ptr))
End Try
Return num3
End Function
您会注意到,这会调用FillFromReader:
Friend Function FillFromReader(ByVal dataset As DataSet, ByVal datatable As DataTable, ByVal srcTable As String, ByVal dataReader As DataReaderContainer, ByVal startRecord As Integer, ByVal maxRecords As Integer, ByVal parentChapterColumn As DataColumn, ByVal parentChapterValue As Object) As Integer
Dim num2 As Integer = 0
Dim schemaCount As Integer = 0
Do
If (0 < dataReader.FieldCount) Then
Dim mapping As SchemaMapping = Me.FillMapping(dataset, datatable, srcTable, dataReader, schemaCount, parentChapterColumn, parentChapterValue)
schemaCount += 1
If (((Not mapping Is Nothing) AndAlso (Not mapping.DataValues Is Nothing)) AndAlso (Not mapping.DataTable Is Nothing)) Then
mapping.DataTable.BeginLoadData
Try
If ((1 = schemaCount) AndAlso ((0 < startRecord) OrElse (0 < maxRecords))) Then
num2 = Me.FillLoadDataRowChunk(mapping, startRecord, maxRecords)
Else
Dim num3 As Integer = Me.FillLoadDataRow(mapping)
If (1 = schemaCount) Then
num2 = num3
End If
End If
Finally
mapping.DataTable.EndLoadData
End Try
If (Not datatable Is Nothing) Then
Return num2
End If
End If
End If
Loop While Me.FillNextResult(dataReader)
Return num2
End Function
看了这一切之后,我可能不得不改变主意。为所有这些编写您自己的实现可能确实有一个可测量的改进。这些函数中的逻辑比我预期的要多,并且在反复调用FillNextResult时会产生一些函数调用开销。下面是一个dataReader用于一般填充datatable的示例。您只需使用DataTable的Load方法并将其传递给DataReader即可:
DataTable dt= new DataTable();
dt.Load(cmd.ExecuteReader()); //cmd being declared as SqlCommand
下面是一个dataReader用于一般填充datatable的示例。您只需使用DataTable的Load方法并将其传递给DataReader即可:
DataTable dt= new DataTable();
dt.Load(cmd.ExecuteReader()); //cmd being declared as SqlCommand
学习如何使用DataReader没有什么坏处,但就性能而言,除非您能找到一个可证明的问题,否则最好还是坚持使用经过测试的DataAdapter。没有具体要求的过早优化就是一个糟糕做法的例子。在它成为一个要求之前,关于优化的优秀观点,我很感激。我想,正如我所读到的那样,使用DataReader具有经验证的性能增益,特别是当行数增加时,它确实需要至少提供一种通用方法来选择预期的行数何时会很大。学习如何使用DataReader没有什么害处,但在性能方面,除非您可以找到一个可证明的问题
您最好坚持使用经过尝试和测试的DataAdapter。没有具体要求的过早优化就是一个糟糕做法的例子。在它成为一个要求之前,关于优化的优秀观点,我很感激。不过我想,由于使用我所阅读的DataReader具有经验证的性能增益,特别是当行数增加时,确实需要至少提供一种通用方法来选择预计行数何时会很大。感谢您将代码拖出,确实提出了一些问题…但由于它在下面使用datareader,可能不值得这样做…感谢您将代码拖出,确实提出了一些问题…但由于它在下面使用datareader,可能不值得这样做。。。