Passion * Technology * Ruthless Competence

Friday, August 17, 2007

DataReaders, LINQ to XML and Range Generation

I'm doing a bunch of database / XML stuff @ work, so I decided to use to VS08 beta 2 so I can use LINQ. For reasons I don't want to get into, I needed a way to convert arbitrary database rows, read using a SqlDataReader, into XML. LINQ to SQL was out, since the code has to work against arbitrary tables (i.e. I have no compile time schema knowledge). But XLinq LINQ to XML helped me out a ton. Check out this example:

const string ns = "{http://some.sample.namespace.schema}";

while (dr.Read())
{
    XElement rowXml = new XElement(ns + tableName,
        from i in GetRange(0, dr.FieldCount)
        select
            new XElement(ns + dr.GetName(i), dr.GetValue(i)));
}

That's pretty cool. The only strange thing in there is the GetRange method. I needed an easy way to build a range of integers from zero to the number of fields in the data reader. I wasn't sure of any standard way, so I wrote this little two line function:

IEnumerable<int> GetRange(int min, int max)
{
    for (int i = min; i < max; i++)
        yield return i;
}

It's simple enough, but I found it strange that I couldn't find a standard way to generate a range with a more elegant syntax. Ruby has standard range syntax that looks like (1..10), but I couldn't find the equivalent C#. Did I miss something, or am I really on my own to write a GetRange function?

Update - As expected, I missed something. John Lewicki pointed me to the static Enumerable.Range method that does exactly what I needed.

Posted By Harry Pierson at 4:55 PM Pacific Daylight Time
ADO.NET | Database | Development | LINQ | Ruby | XML
Friday, August 17, 2007 4:56:34 PM (Pacific Standard Time, UTC-08:00)
AFAIK there's no standard way of doing it, but you could add an extension method to 'Int32'

public static IEnumerable<int> RangeFromZero(this int number)
{
for (int i = 0; i < number; i++)
{
yield return i;
}
}

and have something like

from i in dr.FieldCount.RangeFromZero()

or

from i in dr.FieldCount.Range(0)

with a 'Range' extension method, which is the same that you wrote but a little cooler ;).

Friday, August 17, 2007 9:04:41 PM (Pacific Standard Time, UTC-08:00)
Even better is to add an Extension method to IDataReader to make it enumerable of IDataRecord, I mean semantically it is anyway...

public static IEnumerable<IDataRecord> Enumerate(this IDataReader reader)
{

using (reader)
{

while (reader.Read())

yield return reader;

}
}

Then you can do from r in reader.Enumerate() from i in GetRange(...) etc....
Saturday, August 18, 2007 4:22:32 AM (Pacific Standard Time, UTC-08:00)
I believe System.Linq.Enumerable.Range() is exactly the same as your GetRange method.
John Lewicki
Tuesday, August 21, 2007 9:16:04 AM (Pacific Standard Time, UTC-08:00)
Another minor improvement:

XNamespace ns = "http://some.sample.namespace.schema";
while (dr.Read())
{
XElement rowXml = new XElement(ns + tableName,
from i in Enumerable.Range(0, dr.FieldCount)
select new XElement(ns + dr.GetName(i), dr.GetValue(i)));
}
Anonymous
Comments are closed.
TechEd New Zealand
TechEd Australia

PDC08

patterns & practices
Summit 2008

Change Congress
Recent Bookmarks
Tags .NET Framework (2) ADO.NET (5) Agile (7) AJAX (3) Architecture (283) Guidance (6) Interop (2) Modelling (61) Patterns (7) Process (4) SOA (93) Web Services (5) ASP.NET (22) Battlestar Galactica (3) BI (2) BizTalk (4) Blogging (114) dasBlog (11) Podcasting (4) BPM (1) C# (6) C++ (4) Capitals (5) CardSpace (3) CLR (2) College Football (10) Comedy Central (1) Community (81) Concurrency (6) Consumer Electronics (1) Database (13) Dependency Injection (2) Development (115) C Plus Plus (1) Embedded (5) Lanugages (37) Media (2) P2P (11) Rotor (1) SharePoint (6) SOP (3) DIY (1) DLR (12) Domain Specific Languages (13) Durable Messaging (5) Dynamic Languages (9) Dynamic Silverlight (1) Education (3) Enterprise 2.0 (1) Entertainment (14) ETech (15) F# (42) Functional Programming (12) Game Development (2) Guidance Automation (3) Hardware (8) HawkEye (3) Hockey (29) Home Electronics (1) Home Network (5) Humor (5) IASA (1) Idempotence (3) infrastructure (5) Instrumentation (4) Integration (2) IronPython (19) IronRuby (7) Java (2) Job (3) LINQ (19) Live Mesh (1) Lost (1) Master Data Management (1) Media 2.0 (6) Microsoft (28) MIX06 (2) Mobile Phone (1) Morning Coffee (170) Object Oriented (4) Office (5) Open Source (4) Open Space (2) Operations (3) Other (135) Art (1) Books (1) Family (30) Games (18) General Geekery (26) Home Theater (1) Movies (23) Music (20) Politics (3) Society (1) Sports (37) Working at MSFT (15) Parsing Expression Grammar (16) patterns & practices (2) PDC08 (1) Politics (39) PowerPoint (2) PowerShell (30) Presentation (5) Projects (1) HawkWiki (1) Python (4) Quote of the Day (4) Refactoring (1) Research (2) REST (18) Reuse (5) Robotics (1) Rome (5) Ruby (23) Sci-Fi (2) Scripting (4) Security (3) Service Broker (14) SharePoint (2) Silverlight (15) Social Software (1) Software + Services (2) Software Factories (11) Software Industry (1) Spark (1) SQL Server (2) Stephen Colbert (1) TechEd (7) TechEd06 (1) TechRec League (1) Television (6) Travel (6) Unified Client (1) Unit Testing (4) UX (1) Virtual PC (2) Visual Basic (1) Visual Studio (20) Volta (2) Washington Capitals (34) WCF (31) Web 2.0 (64) Web Services (5) WF (20) Windows Live (23) Xbox (1) Xbox 360 (53) XML (7) XNA (13)
Disclaimer: The information in this weblog is provided "AS IS" with no warranties, and confers no rights. This weblog does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion. Inappropriate comments will be deleted at the authors discretion.