Fastest way to map result of SqlDataReader to object
<p>I'm comparing materialize time between Dapper and ADO.NET and Dapper.  <s>Ultimately, Dapper tend to faster than ADO.NET, though the first time a given fetch query was executed is slower than ADO.NET.</s> a few result show that Dapper a little bit faster than ADO.NET(almost all of result show that it comparable though)<br>
So I think I'm using inefficient approach to map result of SqlDataReader to object.<br>
This is my code  </p>

<pre><code>var sql = "SELECT * FROM Sales.SalesOrderHeader WHERE SalesOrderID = @Id";
        var conn = new SqlConnection(ConnectionString);
        var stopWatch = new Stopwatch();

        try
        {
            conn.Open();
            var sqlCmd = new SqlCommand(sql, conn);

            for (var i = 0; i &lt; keys.GetLength(0); i++)
            {
                for (var r = 0; r &lt; keys.GetLength(1); r++)
                {
                    stopWatch.Restart();
                    sqlCmd.Parameters.Clear();
                    sqlCmd.Parameters.AddWithValue("@Id", keys[i, r]);
                    var reader = await sqlCmd.ExecuteReaderAsync();
                    SalesOrderHeaderSQLserver salesOrderHeader = null;

                    while (await reader.ReadAsync())
                    {
                        salesOrderHeader = new SalesOrderHeaderSQLserver();
                        salesOrderHeader.SalesOrderId = (int)reader["SalesOrderId"];
                        salesOrderHeader.SalesOrderNumber = reader["SalesOrderNumber"] as string;
                        salesOrderHeader.AccountNumber = reader["AccountNumber"] as string;
                        salesOrderHeader.BillToAddressID = (int)reader["BillToAddressID"];
                        salesOrderHeader.TotalDue = (decimal)reader["TotalDue"];
                        salesOrderHeader.Comment = reader["Comment"] as string;
                        salesOrderHeader.DueDate = (DateTime)reader["DueDate"];
                        salesOrderHeader.CurrencyRateID = reader["CurrencyRateID"] as int?;
                        salesOrderHeader.CustomerID = (int)reader["CustomerID"];
                        salesOrderHeader.SalesPersonID = reader["SalesPersonID"] as int?;
                        salesOrderHeader.CreditCardApprovalCode = reader["CreditCardApprovalCode"] as string;
                        salesOrderHeader.ShipDate = reader["ShipDate"] as DateTime?;
                        salesOrderHeader.Freight = (decimal)reader["Freight"];
                        salesOrderHeader.ModifiedDate = (DateTime)reader["ModifiedDate"];
                        salesOrderHeader.OrderDate = (DateTime)reader["OrderDate"];
                        salesOrderHeader.TerritoryID = reader["TerritoryID"] as int?;
                        salesOrderHeader.CreditCardID = reader["CreditCardID"] as int?;
                        salesOrderHeader.OnlineOrderFlag = (bool)reader["OnlineOrderFlag"];
                        salesOrderHeader.PurchaseOrderNumber = reader["PurchaseOrderNumber"] as string;
                        salesOrderHeader.RevisionNumber = (byte)reader["RevisionNumber"];
                        salesOrderHeader.Rowguid = (Guid)reader["Rowguid"];
                        salesOrderHeader.ShipMethodID = (int)reader["ShipMethodID"];
                        salesOrderHeader.ShipToAddressID = (int)reader["ShipToAddressID"];
                        salesOrderHeader.Status = (byte)reader["Status"];
                        salesOrderHeader.SubTotal = (decimal)reader["SubTotal"];
                        salesOrderHeader.TaxAmt = (decimal)reader["TaxAmt"];
                    }

                    stopWatch.Stop();
                    reader.Close();
                    await PrintTestFindByPKReport(stopWatch.ElapsedMilliseconds, salesOrderHeader.SalesOrderId.ToString());
                }
</code></pre>

<p>I used <code>as</code> keyword to cast in nullable column, is that correct?<br>
and this is code for Dapper.  </p>

<pre><code>using (var conn = new SqlConnection(ConnectionString))
        {
            conn.Open();
            var stopWatch = new Stopwatch();

            for (var i = 0; i &lt; keys.GetLength(0); i++)
            {
                for (var r = 0; r &lt; keys.GetLength(1); r++)
                {
                    stopWatch.Restart();
                    var result = (await conn.QueryAsync&lt;SalesOrderHeader&gt;("SELECT * FROM Sales.SalesOrderHeader WHERE SalesOrderID = @Id", new { Id = keys[i, r] })).FirstOrDefault();
                    stopWatch.Stop();
                    await PrintTestFindByPKReport(stopWatch.ElapsedMilliseconds, result.ToString());
                }
            }
        }
</code></pre>