通用DataReader代码(.net)的示例

时间:2009-11-06 01:49:17

标签: .net datareader

由于我对.Net的经验真的开始于为一家公司开发现有的内部应用程序,我觉得我已经接受了这么多糟糕的编码实践而没有意识到这一点。我迫切想要继续前进的是DataSet用于一切。 (我确实得到了强类型数据集,它们确实有一些用途......但不是大多数情况下,例如选择数据)

我正在为通用数据库工作构建一个“帮助器”类...我有一个方法可以返回一个数据表(用于选择等),我猜是默认的(大多数书籍/在线示例) )将使用DataAdapter的Fill方法,但肯定是作为性能增益,想要用读取所有行然后关闭的数据读取器替换它...我猜这是Fill方法在下面工作的方式......但我想如果对大型结果集的性能可能会产生影响,则不要简单地采用懒惰方式。

无论如何,我不能为我的生活找到一个dataReader的例子,用于一般填充数据表...我敢肯定会有好的和坏的例子,因此是一个商定的最佳实践如何执行这样的任务。这样的代码的链接(甚至是帖子)将是辉煌的!我主要是VB.Net,但c#不是障碍。

注意:对不起,如果这听起来也很懒,我只想到这样的例子会到处张贴......不需要重新发明轮子等等谢谢!

3 个答案:

答案 0 :(得分:3)

您无法找到DataReader一般用于填充DataTable的示例的原因是因为您可以使用{Fill()方法执行相同的操作1}},所以你只需重新发明轮子。

通过使用DataReader直接填充DataTable,您不会发现性能优势。

答案 1 :(得分:1)

如果我不得不猜测,与使用带有Fill()方法的sqldataadapter相比,我认为使用sqldatareader填充数据表不会有任何性能优势。

真正验证理论的唯一方法是编写自己的实现并进行比较。但是你也可以查看Fill()正在执行的代码,看看它正在做什么。我建议下载Reflector来查看代码。

我自己就是这么做的。这是调用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()时会产生一些函数调用开销。

答案 2 :(得分:0)

以下是用于一般填充数据表的dataReader的示例。您只需使用DataTable的Load方法并将其传递给DataReader:

DataTable dt= new DataTable();
dt.Load(cmd.ExecuteReader()); //cmd being declared as SqlCommand