Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the most efficient way to convert a DataTable to an object[,]?

I have a bunch of DataTables that need to be converted to object[,] arrays (not object[][] arrays). What's the most efficient way to do this in terms of performance?

I know I can do this by building my object[dt.Rows.Count, dt.Columns.Count] initially, then looping through rows and parsing each row into a place in the array, but I'm fairly sure there's other methods such as using Linq or System.Data-specific features such as dataRow.ToItemArray() which may be more efficient.

My DataTables are of variable sizes, and contain both Dates and Numbers which need to be formatted appropriately, in addition to strings.

For example, if one of my data tables contained

Id    Name    Date                 Value
1     Rachel  1/1/2013 00:00:00    100.0000
2     Joseph  3/31/2012 00:00:00   50.0000
3     Sarah   2/28/2013 00:00:00   75.5000

then I would want an object[,] array containing the exact same data (ideally with headers), but with formatted Dates and Values

arr[x,0] = row[x].Field<int>("Id");
arr[x,1] = row[x].Field<string>("Name");
arr[x,2] = row[x].Field<DateTime>("Date").ToString("M/d/yy");
arr[x,3] = row[x].Field<decimal>("Value").ToString("C2"); // Currency format
like image 598
Rachel Avatar asked Apr 04 '13 13:04

Rachel


1 Answers

Basically we need:

  1. Allocate memory for object[,]

    We cannot do much here.. we need to ensure we allocate memory once and not re-allocate it again. So it's obvious we need create array at once, without using operations like List.Add(...) which internally re-allocate memory blocks.

  2. Then, we need to copy objects from row items into multidimensional array. We could not use Buffer.BlockCopy here as we work with objects. Naturally we can not rely on any memcpy-like behavior, as CLR for each object needs either copy its reference, or do unbox->copy in heap->box for value types. So, the simplest way will be just for.. for.. style.

So, looks like most performance solution here is the intuitive one:

public static object[,] Convert(DataTable dt)
{
    var rows = dt.Rows;
    int rowCount = rows.Count;
    int colCount = dt.Columns.Count;
    var result = new object[rowCount, colCount];

    for (int i = 0; i < rowCount; i++)
    {
        var row = rows[i];
        for (int j = 0; j < colCount; j++)
        {
            result[i, j] = row[j];
        }
    }

    return result;
}
like image 166
Lanorkin Avatar answered Oct 07 '22 13:10

Lanorkin