60

I have DataTable.

DataTable dt = new DataTable();

dt.Columns.Add(new DataColumn("id", Type.GetType("System.Int32")));
dt.Columns.Add(new DataColumn("name", Type.GetType("System.String")));
// more columns here

I need list of "id" values.

Can I do it without loop over all rows in my DataTable and without Linq?

Edit:

After small discussion with Sergei I decided to use loop anyway.

Kamil
  • 13,363
  • 24
  • 88
  • 183

3 Answers3

106

You can use Linq to DataTable:

var ids = dt.AsEnumerable().Select(r => r.Field<int>("id")).ToList();

UPDATE: Without Linq

List<int> ids = new List<int>(dt.Rows.Count);
foreach(DataRow row in dt.Rows)
    ids.Add((int)row["id"]);

Note for efficiency it's better to use row[index] instead of row[columnName]. First one just gets column by index from columns array. Latter gets column index from internal dictionary which maps names to indexes, and only then gets column by index.

Another thing to note is initializing list's capacity with rows count. If you will not do this, then internal array of list will be re-created and copied many times (depends on rows count).

And last thing to say - most efficient way with huge table (if possible) is filtering data on server side.

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • 1
    @TimSchmelter extension methods with C#2? :) – Sergey Berezovskiy May 19 '14 at 10:56
  • First is with Linq, second with loop. This is what I want to avoid. – Kamil May 19 '14 at 10:57
  • @Kamil I bet there was no loop restriction originally. Can you explain what's wrong with loops? – Sergey Berezovskiy May 19 '14 at 10:58
  • 1
    My question text was not changed, when I was editing - I just added bold on these restrictions. You can click "edited ... mins ago" and see edits history. – Kamil May 19 '14 at 11:00
  • Don't delete this answer, it's not for me, but maybe someone will need it. – Kamil May 19 '14 at 11:02
  • @Kamil first editions are not shown on SO. Anyway - whats wrong with loops? If you want to do same thing for each item in some collection, then loops is your friend. Btw Linq also uses loops – Sergey Berezovskiy May 19 '14 at 11:02
  • Sergey, I have a lot of rows there. Im worried about performance, I thought there is some better (more efficient) way to do it. – Kamil May 19 '14 at 11:03
  • @Kamil most efficient way is filtering data on server side (if you are loading DataTable from database). Otherwise loop is simplest and fastest way, its faster than LINQ (don't forget to initialize capacity of list, as I shown in example) – Sergey Berezovskiy May 19 '14 at 11:05
  • OK. I will use loop. My datatable was created for datagridview and it contains filtered data already. I don't want to query database again to get only identifiers, when I have all what I need already in memory (DataTable). – Kamil May 19 '14 at 11:37
  • @Kamil actually I would try both approaches. Even if you already have all data in memory, you can try to make two queries and compare results. But for in-memory retrieving of column values, loop is most efficient approach I think – Sergey Berezovskiy May 19 '14 at 11:41
1
List<int> ids = dt.AsEnumerable().Select(r => r.Field<int>("id")).ToList();

OR

int[] ids = dt.AsEnumerable().Select(r => r.Field<int>("id")).ToArray();
derloopkat
  • 6,232
  • 16
  • 38
  • 45
  • 3
    There are two problems with this answer: 1) LINQ wasn't available in C# 2.0 / .NET Framework 2.0. 2) OP explicitly said they didn't want to use LINQ. – ProgrammingLlama Oct 12 '20 at 01:32
1

AsEnumerable() does not work for me so use:

List<string> ids = dt.Rows.Cast<DataRow>().Select(r => Convert.ToString(r["id"])).ToList();

For other data types use the appropriate Convert.XXX variant.

chara
  • 73
  • 5