I also think that the main problem is in the performance of the DataTable object. You add row-by-row, and all this is done in an object manner, which is traditional for .NET but can drastically slow down performance.
The only alternative to this is to populate the DataTable in one call with the
DataTable.Load() method. It expects an object implementing the
IDataReader interface. We could create a wrapper for iGrid and feed it to the
DataTable.Load() method. The whole construction would look like this:
<Extension>
Friend Function ToDataTable(ByVal grid As iGrid) As DataTable
Dim dt As New DataTable
Using reader As New iGridReader(grid)
dt.Load(reader)
End Using
Return dt
End Function
Class iGridReader : Implements IDataReader
Private sourceGrid As iGrid
Public Sub New(ByVal grid As iGrid)
sourceGrid = grid
End Sub
Public ReadOnly Property Depth As Integer Implements IDataReader.Depth
Get
'...
End Get
End Property
Public ReadOnly Property IsClosed As Boolean Implements IDataReader.IsClosed
Get
'...
End Get
End Property
' Implementation of other members of IDataReader
End Class
But after looking at the source code of DataTable.Load, I am not sure the result will be significantly faster because, it seems, the implementation is also based on creation and addition of the DataRow objects one-by-one. If you have time to experiment, you can try to finish this approach - but you will need to implement about 30 members of IDataReader.
What I would recommend that you try in your original implementation is to call the
DataTable.BeginLoadData() method before you start to add data to the DataTable and then
DataTable.EndLoadData() in the very end before you return the result. Try it for your real data and tell us the result.