<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://www2.sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Adam Machanic : ADO.NET, Performance</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/tags/ADO.NET/Performance/default.aspx</link><description>Tags: ADO.NET, Performance</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>SqlDataReader performance tips</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/07/12/sqldatareader-performance-tips.aspx</link><pubDate>Thu, 13 Jul 2006 01:42:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:98</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>7</slash:comments><comments>http://www2.sqlblog.com/blogs/adam_machanic/comments/98.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=98</wfw:commentRss><description>I just posted a few SqlDataReader performance tips in response to a
newsgroup post; I think they're some pretty good tips, so I'll repeat
them here. &lt;p&gt;
These tips were gleaned from using both &lt;a href="http://www.aisto.com/roeder/dotnet/" target="#"&gt;Lutz Roeder's Reflector&lt;/a&gt; and &lt;a href="http://www.compuware.com/products/devpartner/profiler/default.asp?cid=3019X36&amp;amp;focus=DevPartner&amp;amp;source=Web+%2D+Evaluation+Request&amp;amp;desc=Download+%2D+%27DevPartner+Profiler+Community+Edition%27&amp;amp;offering=DevPartner&amp;amp;sf=1&amp;amp;p=0" target="#"&gt;Compuware's DevPartner Profiler Community Edition&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;
Both of these packages are free, excellent additions to the toolbox of
anyone who wants to write high-performance .NET code. The Reflector
will show you what all of those library routines are &lt;i&gt;really&lt;/i&gt;
doing under the covers (for instance, did you know that the DataView's
FindRows() method does a linear search?) And the Profiler will show you
how long each line of code takes to execute -- accurately, down the
microsecond. Very useful for figuring out where your bottlenecks are!
&lt;/p&gt;&lt;p&gt;
Anyway, on to the tips... Pretty basic stuff, but good to keep in mind:
&lt;/p&gt;&lt;p&gt;
&lt;b&gt;A)&lt;/b&gt; Use an indexer with the ordinal position:
&lt;/p&gt;&lt;p&gt;
Instead of:
&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;pre class="code"&gt;while (reader.read())&lt;br&gt;    object x = reader.GetValue("ColX");&lt;br&gt;&lt;/pre&gt;
&lt;p&gt;
or
&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;pre class="code"&gt;while (reader.read())&lt;br&gt;    object x = reader["ColX"];&lt;br&gt;&lt;/pre&gt;
&lt;p&gt;
do:
&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;pre class="code"&gt;int ColX = reader.GetOrdinal("ColX");&lt;br&gt;while (reader.read())&lt;br&gt;    object x = reader[ColX];&lt;br&gt;&lt;/pre&gt;
&lt;p&gt;Under the covers, the string-based indexer and GetValue both call
GetOrdinal -- so if you're looping through a large rowset GetOrdinal
might be called every single time. Instead, only call it once.
&lt;/p&gt;&lt;p&gt;
&lt;b&gt;B)&lt;/b&gt; Avoid the Get (e.g. GetInt32) methods at all costs, and use static casts instead of converts:
&lt;/p&gt;&lt;p&gt;
Bad:
&lt;/p&gt;&lt;pre class="code"&gt;int x = reader.GetInt32(ColX);&lt;br&gt;&lt;/pre&gt;
&lt;p&gt;
Better:
&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;pre class="code"&gt;int x = Convert.ToInt32(reader[ColX]);&lt;br&gt;&lt;/pre&gt;
&lt;p&gt;
Best:
&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;pre class="code"&gt;int x = (int)reader[ColX];&lt;br&gt;&lt;/pre&gt;
&lt;p&gt;For maximal performance return the SQL Server equivalent of whatever
datatype you'll be casting to (so that you can avoid the Convert
methods.) And avoid NULLs so that you don't have to check for DBNull on
the client.
&lt;/p&gt;&lt;p&gt;
&lt;b&gt;C)&lt;/b&gt; Finally, just like in classic ADO, when using a
SqlDataReader, "open late and close early" is the way to go. Open your
connection at the last possible moment and close it as soon as you're
done reading the data -- this will maximize connection pool
availability.&lt;/p&gt;&lt;br&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=98" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/adam_machanic/archive/tags/ADO.NET/default.aspx">ADO.NET</category><category domain="http://www2.sqlblog.com/blogs/adam_machanic/archive/tags/Performance/default.aspx">Performance</category></item></channel></rss>