通用数据读取器代码(.net)的示例

通用数据读取器代码(.net)的示例,.net,datareader,.net,Datareader,由于我在.Net方面的经验实际上是从为一家公司开发现有的内部应用程序开始的,因此我觉得我在没有意识到的情况下,发现了很多糟糕的编码实践。我拼命想摆脱的一个问题是,数据集用于一切。我确实知道强类型数据集有其存在的地方,它们当然有一些用途……但不是在大多数情况下,例如选择数据 我正在为泛型数据库工作构建一个helper类…我有一个方法可以返回一个数据表,用于选择等。我猜默认情况下,books/online中的大多数示例都会使用DataAdapter的Fill方法,但肯定是作为性能增益,我想用一个读取

由于我在.Net方面的经验实际上是从为一家公司开发现有的内部应用程序开始的,因此我觉得我在没有意识到的情况下,发现了很多糟糕的编码实践。我拼命想摆脱的一个问题是,数据集用于一切。我确实知道强类型数据集有其存在的地方,它们当然有一些用途……但不是在大多数情况下,例如选择数据

我正在为泛型数据库工作构建一个helper类…我有一个方法可以返回一个数据表,用于选择等。我猜默认情况下,books/online中的大多数示例都会使用DataAdapter的Fill方法,但肯定是作为性能增益,我想用一个读取所有行然后关闭的数据读取器来代替它…我想这就是Fill方法在下面的工作方式…但是如果大型结果集上的性能可能会受到影响,我不想简单地采用懒惰的方式

无论如何,我一生都找不到一个dataReader被用来一般填充datatable的例子……我确信会有好的和坏的例子,因此在如何执行这样的任务方面会有一个一致的最佳实践。一个链接,甚至一篇文章到这样的代码将是辉煌的!我主要是VB.Net,但c不是障碍


注意:如果这听起来也很懒,很抱歉,我只是想这类例子会被张贴在任何地方…不需要重新发明轮子等。谢谢

找不到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,可能不值得这样做。。。