Well I always thought of a DataReader when it comes to performance but I can't forget to keep the data in memory and also keep in mind that the DataReader works in connected mode. So I came up with a mixed approach; reading the fetched the data from a DataReader and then put the data into a DataTable. The next thing was to make it reusable so finally I did some juggling with the code and came up with the code below that can convert your DataReader object to a DataTable.
I always use IDataReader to receive the object returned from the Command.ExecuteReader() method.
You can get the schema of the Table a by method that is available through the IDataReader interface GetSchemaTable(). I'll use this method to get the schema of the table that IDataReader is holding. Then I create a new DataTable using the data we received from the schema and start populating it by using the data in the DataReader. See the below snippet; I've put all the ideas together and created this method GetDataTableFromDataReader().
public DataTable GetDataTableFromDataReader(IDataReader dataReader)
{
DataTable schemaTable = dataReader.GetSchemaTable();
DataTable resultTable = new DataTable();
foreach (DataRow dataRow in schemaTable.Rows)
{
DataColumn dataColumn = new DataColumn();
dataColumn.ColumnName = dataRow["ColumnName"].ToString();
dataColumn.DataType = Type.GetType(dataRow["DataType"].ToString());
dataColumn.ReadOnly = (bool)dataRow["IsReadOnly"];
dataColumn.AutoIncrement = (bool)dataRow["IsAutoIncrement"];
dataColumn.Unique = (bool)dataRow["IsUnique"];
resultTable.Columns.Add(dataColumn);
}
while (dataReader.Read())
{
DataRow dataRow = resultTable.NewRow();
for (int i = 0; i < resultTable.Columns.Count - 1; i++)
{
dataRow[i] = dataReader[i];
}
resultTable.Rows.Add(dataRow);
}
return resultTable;
}
Now you can use this method to fetch the data in the DataReader and then get the DataTable from it. Its really fast I'm telling you! Yeah people can ask me about the complexity of creating another table's schema and looping through the records, but this method is still worth using over the SqlDataAdapter class.
Let me go though a small demo over this. Let's create a DB connection and use this method and the Adapter method to get the Performance records.
public class DAL
{
static SqlConnection connection;
public DAL()
{
connection = new SqlConnection();
connection.ConnectionString = System.Configuration.ConfigurationSettings.AppSettings["myConnectionString"];
}
public DataTable GetDataTableByAdapter(string query)
{
connection.Open();
DateTime start = DateTime.Now;
DataTable dt = new DataTable();
new SqlDataAdapter(query, connection).Fill(dt);
TimeSpan ts = DateTime.Now.Subtract(start);
System.Diagnostics.Trace.Write("Time Elapsed in Adapter: "+ts.TotalMilliseconds);
connection.Close();
return dt;
}
public DataTable GetDataTableFast(string query)
{
connection.Open();
DateTime start = DateTime.Now;
IDataReader rdr = new SqlCommand(query, connection).ExecuteReader();
DataTable resultTable = GetDataTableFromDataReader(rdr);
TimeSpan ts = DateTime.Now.Subtract(start);
System.Diagnostics.Trace.Write("Time Elapsed in Custom : " + ts.TotalMilliseconds);
connection.Close();
return resultTable;
}
}
Now lets call this method in a console application and then we'll go through the Trace where the code will be writing the elapsed time in individual operation.
static void Main(string[] args)
{
DAL dal = Singleton<DAL>.Instance;
string query = "Select * from Production.Product";
DataTable dt1 = dal.GetDataTableFast(query);
DataTable dt = dal.GetDataTableByAdapter(query);
System.Console.Read();
}
Now Run the code and let's have a look at figures. I ran this program 2 times just to make sure counts are correct
First Run - Time Elapsed in Adapter: 93.0053 Time Elapsed in Custom : 13.0008
Second Run - Time Elapsed in Adapter: 129.0074 Time Elapsed in Custom: 14.0008
So I'm sure you must be impressed with the performance here. Moreover you can make it faster by using the Parallel.For() and Parallel.Foreach() loop if you are working on .NET 4.0 and have a multicore processor.
Get Smarter. Get Faster!! Nobody wants to wait.

ורדה שוויבלPosted Jul 16, 2019, 3:26 AM
You saved my day, Thank
Sr KarthigaPosted Feb 26, 2016, 9:14 AM
good one
Sr KarthigaPosted Feb 26, 2016, 9:14 AM
nice explanation
Amit ChoudharyPosted Oct 25, 2012, 6:31 AM
Thanks for finding the Errata in the code. I appreciate that. For comparing performance we already have debt on these two. Check'em out here and do mention you findings, it will give others to re-think about Adpater vs Reader: http://stackoverflow.com/questions/1676753/sqldataadapter-vs-sqldatareader http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/c2d762fd-f4a0-4875-8bb8-42f7480e97c8/ :)
Atul PandeyPosted Oct 10, 2012, 5:21 AM
Oh My God! I tested and the result is opposite! SqlDataAdapter is FASTER than IdataReader. (I tested with 500 records, 10000 records and 600,000 records)
Atul PandeyPosted Oct 10, 2012, 4:55 AM
Thank Amit Choudhary for your helpful article! But i want to discuss a litle about the row: for (int i = 0; i < resultTable.Columns.Count - 1; i++) { dataRow[i] = dataReader[i]; } I think that it'd be better if for (int i = 0; i < resultTable.Columns.Count; i++)
Amit ChoudharyPosted Oct 7, 2011, 2:07 AM
It was Around 500 + records against the Product table of AdventureWorks DB. Well if you want I'll run it against the large records and will update the stats.
Javeed M ShaikhPosted Oct 6, 2011, 5:20 PM
Your test was for how many number of records?