Linq over DataTable.Rows

Currently you can't directly use Linq over and DataSet/DataTable/DataRowCollection/etc. class. Trying something like this won't work:

var q = from r in table.Rows select r;

Enabling Linq over the classes mentioned above is under consideration by Microsoft and I don't doubt they will enable them. But if you wish to do it now, here is the simple workaround. Everything you need to do (the Linq requires) is that the class implements IEnumerable<T>. So, I will create a generic class that wraps around any IEnumerable and implements IEnumerable<DataRow>. Here is the code:

    // simple wrapper that implements IEnumerable<T>
    internal class LinqList<T>: IEnumerable<T>, IEnumerable
        IEnumerable items;

        internal LinqList(IEnumerable items)
            this.items = items;

        #region IEnumerable<DataRow> Members
        IEnumerator<T> IEnumerable<T>.GetEnumerator()
            foreach (T item in items)
                yield return item;

        IEnumerator IEnumerable.GetEnumerator()
            IEnumerable<T> ie = this;
            return ie.GetEnumerator();

The code is pretty straightforward, isn't it. And here is a simple test:

  // create and fill table
  DataTable table = new DataTable();
  table.Columns.Add("Id", typeof(int));
  table.Rows.Add(new object[]{1});
  table.Rows.Add(new object[]{2});
  table.Rows.Add(new object[]{3});
  // create a wrapper around Rows
  LinqList<DataRow> rows = new LinqList<DataRow>(table.Rows);
  // do a simple select
  IEnumerable<DataRow> selectedRows = from r in rows
         where (int)r["Id"] == 2
         select r;
  // output result
  foreach (DataRow row in selectedRows)

It is not pretty as it could be but it certainly works. And if you want you can create your own strong typed table implementation that exposes LinqList<DataRow> Rows property. Perhaps using a code generator such as CodeSmith instead of doing boring work yourself.

Comments (3) -

  • Dln

    3.2.2006 8:38:17 | Reply

    The non-generic type 'System.Collections.IEnumerable' cannot be used with type arguments

    on word  -'IEnumerable' ???

  • Miha Markic

    4.2.2006 0:46:56 | Reply

    Hi Din,

    Did you include System.Collections.Generic namespace? Anyway, check out Sahil's solution, too.