2009-12-29
if-read-do-while-read
Here’s a construction I occasionally need when reading items from a IDataReader: to execute some code before and after reading through the IDataReader, but only if there are rows in the IDataReader.
One option is to use a boolean variable that determines whether the collection has items, like this:
using (IDataReader reader = command.ExecuteReader())
{
bool hasRows = false;
while (reader.Read())
{
if (!hasRows)
{
hasRows = true;
Before();
}
During();
}
if (hasRows)
After();
}
But the following construction (which I call the if-read-do-while-read construction) does not need the boolean variable and is cleaner:
using (IDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
Before();
do
{
During();
}
while (reader.Read());
After();
}
}
Here's a practical example: creating HTML-code with a UL-list for the data, but only if there are items:
StringBuilder html = new StringBuilder();
using (IDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
html.Append("<ul>");
do
{
html.AppendFormat(
"<li>{0}",
reader.GetValue(0));
}
while (reader.Read());
html.Append("</ul>");
}
}
You could use the same technique on an IEnumerable<T>, but you wouldn't be able to use foreach anymore:
using (var enumerator = collection.GetEnumerator())
{
if (enumerator.MoveNext())
{
Before();
do
{
var item = enumerator.Current;
During();
}
while (enumerator.MoveNext());
After();
}
}
Comments:
Post a Comment
Links to this post:
I bet you could clean this up nicely by using delegates and anonymous functions. The boilerplate logic could go in the primary method that called out to the delegates. However, I do like the "if" version as well, it looks very clean.
Tanton, I just wrote a new blog post that implements your idea as an extension method on IDataReader: http://blog.tcx.be/2010/01/if-read-do-while-read-part-2.html
Links to this post:
