代码之家  ›  专栏  ›  技术社区  ›  davidsleeps

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

  •  1
  • davidsleeps  · 技术社区  · 15 年前

    随着我在.NET的经验真正开始于为一家公司开发现有的内部应用程序,我觉得我在没有意识到这一点的情况下,接受了很多糟糕的编码实践。我正拼命地试图摆脱的一个问题是,数据集用于所有事情。(我确实知道强类型数据集在那里,而且它们确实有一些用途……但对于大多数情况,例如选择数据,则没有这种用途)

    我正在为一般的数据库工作构建一个“helper”类……我有一个返回数据表(用于selects等)的方法,我猜在默认情况下(以及在books/online中的大多数示例),它将使用dataadapter的fill方法,但肯定是为了提高性能,我想用一个读取所有行然后关闭的数据读取器来替换它……它我猜填充方法是如何在下面工作的……但是如果大型结果集的性能可能会受到影响,我宁愿不简单地采用懒惰的方式。

    不管怎样,我找不到一个数据阅读器的例子,它被用来一般地填充一个数据表……我确信会有好的和坏的例子,因此会有一个关于如何执行这样一个任务的一致的最佳实践。一个链接(甚至一个帖子)到这样的代码将是辉煌的!我主要是vb.net,但c不是障碍。

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

    3 回复  |  直到 13 年前
        1
  •  3
  •   Robert Harvey    15 年前

    你找不到 DataReader 通常用于填充 DataTable 是因为你可以用 Fill() 方法在 DataSet 所以你只需要重新发明轮子。

    通过直接用DataReader填充数据表,您不会发现性能优势。

        2
  •  1
  •   Steve Wortham    15 年前

    如果不得不猜测,与使用sqldataadapter和fill()方法相比,使用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()时也会有一些函数调用开销。

        3
  •  0
  •   Anthony    13 年前

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

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