由于我对.Net的经验真的开始于为一家公司开发现有的内部应用程序,我觉得我已经接受了这么多糟糕的编码实践而没有意识到这一点。我迫切想要继续前进的是DataSet用于一切。 (我确实得到了强类型数据集,它们确实有一些用途......但不是大多数情况下,例如选择数据)
我正在为通用数据库工作构建一个“帮助器”类...我有一个方法可以返回一个数据表(用于选择等),我猜是默认的(大多数书籍/在线示例) )将使用DataAdapter的Fill方法,但肯定是作为性能增益,想要用读取所有行然后关闭的数据读取器替换它...我猜这是Fill方法在下面工作的方式......但我想如果对大型结果集的性能可能会产生影响,则不要简单地采用懒惰方式。
无论如何,我不能为我的生活找到一个dataReader的例子,用于一般填充数据表...我敢肯定会有好的和坏的例子,因此是一个商定的最佳实践如何执行这样的任务。这样的代码的链接(甚至是帖子)将是辉煌的!我主要是VB.Net,但c#不是障碍。
注意:对不起,如果这听起来也很懒,我只想到这样的例子会到处张贴......不需要重新发明轮子等等谢谢!
答案 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