Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding multiple rows to DataTable

I know two ways to add new row with data to a DataTable

string[] arr2 = { "one", "two", "three" };
dtDeptDtl.Columns.Add("Dept_Cd");

for (int a = 0; a < arr2.Length; a++)
{
    DataRow dr2 = dtDeptDtl.NewRow();
    dr2["Dept_Cd"] = DeptCd[a];
    dtDeptDtl.Rows.Add(dr2);
}

for (int a = 0; a < arr2.Length; a++)
{
    dtDeptDtl.Rows.Add();
    dtDeptDtl.Rows[a]["Dept_Cd"] = DeptCd[a];
}

Both the above methods will give me the same result i.e One Two Three will be added in DataTable in seperate rows.

But my question is that what is the difference between both the steps and which one is better way performance wise?

like image 857
Anuj Avatar asked Aug 27 '13 10:08

Anuj


1 Answers

Some decompiler observations

In both scenarios, a different overload of the System.Data.DataRowCollection.Add method is being used.

The first approach uses:

public void Add(DataRow row)
{
    this.table.AddRow(row, -1);
}

The second approach will use:

public DataRow Add(params object[] values)
{
    int record = this.table.NewRecordFromArray(values);
    DataRow dataRow = this.table.NewRow(record);
    this.table.AddRow(dataRow, -1);
    return dataRow;
}

Now, take a look at this little beast:

internal int NewRecordFromArray(object[] value)
{
    int count = this.columnCollection.Count;
    if (count < value.Length)
    {
        throw ExceptionBuilder.ValueArrayLength();
    }
    int num = this.recordManager.NewRecordBase();
    int result;
    try
    {
        for (int i = 0; i < value.Length; i++)
        {
            if (value[i] != null)
            {
                this.columnCollection[i][num] = value[i];
            }
            else
            {
                this.columnCollection[i].Init(num);
            }
        }
        for (int j = value.Length; j < count; j++)
        {
            this.columnCollection[j].Init(num);
        }
        result = num;
    }
    catch (Exception e)
    {
        if (ADP.IsCatchableOrSecurityExceptionType(e))
        {
            this.FreeRecord(ref num);
        }
        throw;
    }
    return result;
}

Especially, note the this.columnCollection[i][num] = value[i];, which will call:

public DataColumn this[int index]
{
    get
    {
        DataColumn result;
        try
        {
            result = (DataColumn)this._list[index];
        }
        catch (ArgumentOutOfRangeException)
        {
            throw ExceptionBuilder.ColumnOutOfRange(index);
        }
        return result;
    }
}

Moving forward, we discover that actually _list is an ArrayList:

private readonly ArrayList _list = new ArrayList();

Conclusion

In order to summarize the above, if you are using dtDeptDtl.Rows.Add(); instead of dtDeptDtl.Rows.Add(dr2);, you will get a performance degradation which will increase exponentially, as the number of columns grows. The responsible line for the degradation is call to the NewRecordFromArray method, which iterates over an ArrayList.

Note: This can be easily tested if you add, let's say, 8 columns to the table and make some tests in a for looping 1000000 times.

like image 82
Alex Filipovici Avatar answered Oct 10 '22 21:10

Alex Filipovici