Converting a DataReader to IEnumerable Using Iterators and Yield in VB.NET

The yield keyword is incredibly useful when you need to convert collections into other types of collections. Unfortunately VB programmers were left out until late last year. Since the Async CTP 3 the yield keyword and Iterator functions have been available for Visual Basic .NET.

You can find lots of examples of this around for C# but some of us corporate contract programmers sometimes have to use VB.NET! 

Here's an example of how to create a list of objects from a DataReader using Yield. To run this you will need to download the Visual Studio Async CTP 3 or .NET 4.5 RC.

So our goal is to take a set of rows from a database, which we access via a DataReader. We want to convert each row into an object, and return all those objects as an IEnumerable - in this case a List(Of T).

Here's our class to store the data as objects. Notice it has a static method to create an instance of itself using a row from a DataReader.


Class StudentRecord
        Public StudentId
        Public UnitCode
        Public HoursPerWeek
        Public NumberOfWeeks
        Public TotalHours
 
        Public Shared Function Create(dr As IDataRecordAs StudentRecord
            Return New StudentRecord With {
                .StudentId = GetStringFromReader(dr, "studentId"),
                .UnitCode = GetStringFromReader(dr, "unitCode"),
                .HourPerWeek = GetDoubleFromReader(dr, "hoursPerWeek"),
                .NumberOfWeeks = GetIntFromReader(dr, "numWeeks"),
                .TotalHours = .HoursPerWeek * .NumberOfWeeks
                }
        End Function
End Class


(GetStringFromReader and similar are helper function from my common utility library. They just return the specified column's value as the required type.)

Next, we have our main loop where we retrieve the data from the database, and then pass it to the conversion method. Let's call it GetData. It queries the DB and returns the list of StudentRecord objects. The details of GetReader aren't important - it just creates a DataReader based on the SqlDatabase and SqlCommand objects.

Note: this code is just for example - we wouldn't normally necessarily have the SQL statement right here!

The interesting part is the call to GetEnumerator. We pass in the type (aka generic type T) we want to get back, as well as the data reader and a function parameter for the static method we saw above. Lastly we convert the IEnumerable it returns to a list.


Private Function GetData() As List(Of StudentRecord)
        Dim db As New SqlDatabase(CONN_STRING)
 
        Using cmd As SqlCommand =
            SqlDatabaseHelper.CreateSqlStringCommand(db,
                                   "SELECT * from students")
            ' Create data reader             Using dr As DbDataReader = GetReader(db, cmd)                 Return GetEnumerator(Of StudentRecord)(dr, AddressOf StudentRecord.Create).ToList()             End Using         End Using     End Function


Last but not least - here's where we convert each row from the DataReader into a StudentRecord. It's quite simple and this is the great bit about how Yield works. We simply pass each row from the reader into the function specifed in the generator function parameter, and it outputs a constructed StudentRecord object. The Yield functionality takes care of executing the StudentRecord.Create method, collecting up all the created objects and returning them as an IEnumerable object.

We can get rid of the reader here because once we've completely iterated we have all the data we need in the IEnumerable.


Public Iterator Function GetEnumerator (Of T)(reader As IDataReader, generator As Func(Of IDataRecordT)) As IEnumerable(Of T)
        Try
            While (reader.Read())
                Yield generator(reader)
            End While
        Catch ex As Exception
            Debug.WriteLine(ex.Message)
        Finally
            reader.Dispose()
        End Try
End Function

So there you have it - a functional Yield scenario written in VB.NET. Personally I love these patterns as they allow you to write much cleaner and testable code Hope it helps!

3 comments:

Anonymous said...

Try adding a WHERE to the SQL statement and let me know if it fail.

Unknown said...

Hi Anonymous Commenter,

Using a where clause works fine in my project. What error message are you seeing?

Cheers

Anonymous said...

It is simply the best and easiest way I've found. It works fine.
Thanks a lot Randomtech!!! Your kung-fu is the best.

Tags

windows (10) microsoft (9) .net (6) google chrome (5) windows 7 (5) asp.net (4) google (4) google browser (4) development (3) javascript (3) mssql (3) rss (3) sql server (3) wordpress (3) automation (2) blogging (2) css (2) database (2) firefox (2) get all wordpress images (2) gmail (2) google docs (2) intel (2) internet explorer (2) linux (2) linux commands (2) microsoft word (2) mysql (2) netsh (2) network issue (2) proxy (2) seo tips (2) shell (2) sun (2) tfs (2) videos (2) wget (2) windows networking (2) windows vista (2) winhttp (2) .net 3.5 (1) .net 4.5 (1) .net async ctp3 (1) .net framework 4.0 (1) 404 (1) JungleDisk (1) access (1) active directory (1) addons (1) adobe acrobat (1) adobe dlm (1) adobe reader (1) adp (1) adsense (1) adtoll (1) adwords (1) amazon (1) antivirus (1) asp.net 4.0 (1) authentication (1) back links (1) backlinks (1) bacula (1) bash (1) batch files (1) blogger (1) box (1) browser exploits (1) category rss (1) cell phone (1) cell phone comparison (1) charting (1) cheap cell phones (1) cheap laptop upgrades (1) checkout (1) chrome (1) chrome.manifest (1) cloud (1) cloud hosting (1) cloud vps (1) code (1) color chart (1) colour chart (1) conditional formatting (1) config (1) configuration (1) context menu (1) copy (1) corrupt (1) credentials (1) cross-reference (1) database scripts (1) dba scripts (1) debian (1) decrypt (1) delete file windows vista (1) delete files (1) dell (1) dell laptop (1) dell studio (1) dell studio 1537 (1) dhcp (1) directory size (1) div (1) dns (1) document properties (1) dotnet (1) download (1) dreamhost (1) dreamhost coupon (1) dreamhost promo (1) dreamhost promo code (1) drive letter (1) drivers (1) duplicate content (1) editpad pro (1) encrypt (1) encryption (1) error (1) error code (1) excel (1) exception (1) external hard drive (1) facebook (1) faviconize (1) feeds (1) firefox 3 rc1 (1) firefox 3.1 (1) firefox addons (1) firefox tabs (1) firewall (1) firewall script (1) fix (1) fix .net framework (1) foreign keys (1) gmail 2.0 (1) gmail error (1) google chrome 2.0 (1) google chrome dev (1) google chrome exploit (1) google reader (1) google reader tags (1) gtdinbox (1) hard drive (1) hex color (1) hex colour (1) htaccess (1) html (1) html 5 (1) iis6 (1) installation (1) ipod touch (1) ipod touch 2g (1) ipod touch freeze (1) ipod touch magnet case (1) ipod touch magnet case problem (1) ipod touch problem (1) iterator pattern (1) itunes (1) java (1) joomla (1) jquery (1) laptop (1) laptop upgrade (1) laptops (1) latex (1) leeching (1) like button (1) link checker (1) linkbacks (1) linq (1) linqdatasource (1) lost password (1) making money online (1) map drive (1) mega cheap phones (1) microsoft excel (1) microsoft signature (1) microsoft store (1) microsoft web deploy (1) microsoft windows (1) microsoft word 2007 (1) minimize firefox tabs (1) mozy (1) ms word (1) msdeploy (1) msdtc (1) nant (1) netstumbler (1) network path not found (1) network path was not found (1) network problem (1) networking (1) new movies (1) nintendo (1) nirsoft (1) nocheckbrowser (1) number (1) odf (1) odt (1) online backups (1) open source browser (1) openoffice (1) oracle (1) oracle client (1) photoshop (1) phpmyadmin (1) podcast (1) powershell (1) pr checker (1) productivity (1) proxy server (1) proxycfg (1) putty (1) recover (1) registry (1) reinstall windows 7 (1) remote desktop (1) remove (1) repair (1) reset joomla admin password (1) rewrite (1) rsa (1) sandy bridge laptop (1) seagate momentus xt (1) seo tools (1) sequence (1) server monitoring (1) sftp (1) social networks (1) softlayer (1) soulseek (1) spreadsheet (1) spreadsheet formula (1) sql (1) sql scripts (1) sql server management studio (1) sqlclient (1) ssh (1) ssis (1) ssl (1) ssms (1) subst (1) tabmixplus (1) telstra (1) text editor (1) trust (1) unlock cell phone (1) unlock mobile phone (1) upgrade laptop hard drive (1) user management (1) vb.net (1) video download (1) virtual server (1) visual studio (1) vodafone (1) vodafone australia (1) vps (1) vps.net (1) wd external drive (1) web deploy (1) web dev (1) web development (1) web hosting (1) web security (1) webdev (1) webmail (1) webmaster tips (1) western digital (1) wifi networks (1) wii (1) win7 (1) windows 7 backup (1) windows 7 gadgets (1) windows 8 (1) windows 8 antivirus (1) windows error (1) windows live (1) windows live essentials (1) windows live toolbar (1) windows tips (1) windows web development (1) windows xp (1) winxp (1) wireless networks (1) word tips (1) wordpress 2.7 (1) wordpress plugin (1) wp super cache (1) yield (1) youtube download (1) youtube playlist download (1)