views:

81

answers:

3

Hi,

I'm trying to perform a simple Linq "find first" query on a typed DataTable, but cannot seem to get the syntax correct.

(If I don't use typed data table/row objects, things work just fine.)

I have this...

class Program
{
  static void Main(string[] args)
  {
     MyDataTable table = new MyDataTable("table");

     table.Rows.Add(1, "Hello");
     table.Rows.Add(2, "There");
     table.Rows.Add(1, "World");
     table.Rows[0].Delete();

     Func<MyDataRow, Boolean> func = (row) => row.One == 1;

     var row1 = table.AsEnumerable().First(func);
  }

  private class MyDataTable : DataTable
  {
     public MyDataTable()
     {
        this.Columns.Add("One", typeof(Int32));
        this.Columns.Add("Two", typeof(String));
     }
     public MyDataTable(String tableName) : this() { this.TableName = tableName; }

     protected override Type GetRowType()
     {
        return typeof(MyDataRow);
     }

     protected override DataRow NewRowFromBuilder(DataRowBuilder builder)
     {
        return new MyDataRow(builder);
     }

     public IEnumerable<MyDataRow> AsEnumerable()
     {
        foreach (MyDataRow row in this.Rows)
        {
           yield return row;
        }
     } 
  }

  private class MyDataRow : DataRow
  {
     internal MyDataRow(DataRowBuilder builder) : base(builder) { }
     public int One
     {
        set { this["One"] = value; }
        get { return Convert.ToInt32(this["One"]); }
     }
     public String Two
     {
        set { this["Two"] = value; }
        get { return Convert.ToString(this["Two"]); }
     }
  }
}

I had tried this as well (which clearly didn't work);

  private class MyDataTable : DataTable
  {
       :
     public EnumerableRowCollection<MyDataRow> AsEnumerable()
     {
        return base.AsEnumerable();
     }

  }

So, my question is this:

In order to use Linq to determine the existence of one or more records in a typed data table, what do I need to implement ? Do I, for example, need to override "AsEnumerable", or could I write a "First" method on the MyDataTable class ?

Or do I have to do something cludgy like cast MyDataTable as a DataTable and treat the rows as DataRow objects ?

Thanks,

A: 

First of all, your code seems to work here. row1 is not null.

If you want to check if a record exists, you would use the Linq method Any(r => r.One == 1).

testalino
My apologies. It took a while to get to that point and I must have missed the point that it did compile.
Ross Watson
+2  A: 

Use Cast to convert an IEnumerable to strongly-typed IEnumerable<T>.

Danny Chen
The IEnumerable returned in his function is already strongly typed, otherwise the code wouldn't compile because .One would be unknown.
testalino
A: 

Instead of writing your own implementation of AsEnumerable( ) you could reference the assembly System.Data.DataSetExtensions

Then you could do:

table.AsEnumerable( ).Where( item => item.Field<int>( "One" ) == 1 ).First( );

You need following using statements:

using System.Data.Linq;
using System.Linq;
Viper