Contents
We can get direct access if using the Rows and Columns collections on a DataTable. The DataTable.Select method allows us to filter.
Better is to use a DataView. Filter, sort, find, and you get proper handling of deleted row values.
Example code is in project DataSet\DtView.
Here is the setup for the DataTable we will be using.
static DataSet ds;
static DataTable items;
private static void CreateDataTable()
{
ds = new DataSet("fred");
items = new DataTable("Items");
ds.Tables.Add(items);
DataColumn dc;
dc = new DataColumn();
dc.ColumnName = "id";
dc.DataType = typeof(Int32);
dc.ReadOnly = true;
dc.AllowDBNull = false;
dc.Unique = true;
dc.AutoIncrement = true;
dc.AutoIncrementSeed = 100;
dc.AutoIncrementStep = 10;
items.Columns.Add(dc);
dc = new DataColumn();
dc.ColumnName = "name";
dc.DataType = typeof(string);
dc.AllowDBNull = false;
dc.Unique = true;
items.Columns.Add(dc);
dc = new DataColumn();
dc.ColumnName = "color";
dc.DataType = typeof(string);
dc.AllowDBNull = true;
items.Columns.Add(dc);
items.PrimaryKey = new DataColumn[] { items.Columns["id"] };
}
static string[] itemNames = { "widget", "freeble", "thingie", "whatzit", "geegaw" };
static string[] itemColors = { "blue", "blue", "blue", "blue", "red" };
private static void EnterInitialData()
{
DataRow row;
for (int i = 0; i < itemNames.Length; ++i)
{
row = items.NewRow();
row["name"] = itemNames[i];
row["color"] = itemColors[i];
items.Rows.Add(row);
}
// Make the initial rows Unchanged
items.AcceptChanges();
}
private static void EditDataTable()
{
DataRow row;
row = items.Rows[0];
row.Delete();
row = items.Rows[1];
row["color"] = "teal";
row = items.NewRow();
row["name"] = "thingamabob";
row["color"] = "green";
items.Rows.Add(row);
}
The DataTable.Rows value is a DataRowCollection. THat collection has a Find method to use when searching for records by primary key.
private static void FindData()
{
DataRow foundRow = items.Rows.Find(110);
if (foundRow == null)
Console.WriteLine("Didn't find it");
else
{
Console.WriteLine("Found a row");
PrintRow(foundRow); // see below
Console.WriteLine("------");
}
}
The overload of Find used above takes a single key value. If the table has a multi-field key, there is an overload that takes an object array.
DataRow foundRow = dataTable.Find( new object[] { key1, key2, key3 } );
The Select method of the DataTable allows you to specify several criteria:
DataRow[] rows = dt.Select(filter,sort,state);
There are overloads taking 0, 1, or 2 arguments that default the trailing parameters.
| Member name | Description | Value |
|---|---|---|
| Added | A new row. | 4 |
| CurrentRows | Current rows including unchanged, new, and modified rows. | 22 |
| Deleted | A deleted row. | 8 |
| ModifiedCurrent | A current version, which is a modified version of original data (see ModifiedOriginal). | 16 |
| ModifiedOriginal | The original version (although it has since been modified and is available as ModifiedCurrent). | 32 |
| None | None. | 0 |
| OriginalRows | Original rows including unchanged and deleted rows. | 42 |
| Unchanged | An unchanged row. | 2 |
Because of the possibility of seeing Deleted rows,
some caution must be taken. I wrote the following method to display the values
in a row:
private static void PrintData(string p, DataRow[] rows)
{
Console.WriteLine("------");
Console.WriteLine(p);
foreach (DataRow row in rows)
PrintRow(row);
Console.WriteLine("------");
}
private static void PrintRow(DataRow row)
{
foreach (DataColumn col in row.Table.Columns)
if (row.HasVersion(DataRowVersion.Default))
Console.Write("\t{0}", row[col]);
else
Console.Write("\t{0}", row[col, DataRowVersion.Original]); // is deleted
Console.WriteLine();
}
Here are some calls to Select, with the output shown next to it.
items.Select() |
110 freeble teal |
items.Select("color='blue'") |
120 thingie blue |
items.Select("color='blue'",
"name DESC") |
130 whatzit blue |
items.Select("","",
DataViewRowState.Added) |
150 thingamabob green |
items.Select("","",
DataViewRowState.CurrentRows) |
110 freeble teal |
items.Select("", "",
DataViewRowState.Deleted) |
100 widget blue |
items.Select("", "",
DataViewRowState.ModifiedCurrent) |
110 freeble teal |
items.Select("", "",
DataViewRowState.ModifiedOriginal) |
110 freeble teal |
items.Select("", "",
DataViewRowState.OriginalRows) |
100 widget blue |
items.Select("", "",
DataViewRowState.Unchanged) |
120 thingie blue |
You see no difference between ModifiedCurrent and ModifiedOriginal here; both select all Modified rows. You will see difference when these enum values are used in a DataView. See below.
DataView dv1 = new DataView(); // not attached to any table
DataView dv2 = new DataView(items); // attached to DataTable items, default filter, sort, CurrentRows
DataView dv3 = new DataView(items,"color='blue'","name DESC",DataViewRowState.CurrentRows);
// specifying filter, sort, rowstate
| Property | Description |
|---|---|
| RowFilter | Specify a SQL WHERE clause to select rows. |
| RowStateFilter | Specify a value to DataRowViewState to select which rows/values are seen. |
| Sort | Specify a SQL ORDER BY clause to sort rows. An index will be created on these columns. |
| ApplyDefaultSort | Set the Sort property to match the primary key field(s). Only works when the Sort property is null or the empty string. |
| DataViewRowState | Description |
|---|---|
| CurrentRows | The Current row version of all Unchanged, Added, and Modified rows. |
| Added | The Current row version of all Added rows |
| Deleted | The Original row version of all Deleted rows. |
| ModifiedCurrent | The Current row version of all Modified rows. |
| ModifiedOriginal | The Original row version of all Modified rows. |
| None | No rows. |
| OriginalRows | The Original row version of all Unchanged, Modified, and Deleted rows. |
| Unchanged | The Current row version of all Unchanged rows. |
And away we go. First, a few helper to write out things of interest.
private static void PrintViewInfo(DataView view)
{
Console.WriteLine("View settings:");
Console.WriteLine(" AllowDelete: {0}", view.AllowDelete);
Console.WriteLine(" AllowEdit: {0}", view.AllowEdit);
Console.WriteLine(" AllowNew: {0}", view.AllowNew);
Console.WriteLine(" Filter: {0}", view.RowFilter);
Console.WriteLine(" State: {0}", view.RowStateFilter);
Console.WriteLine(" Sort: {0}, Default: {1}", view.Sort, view.ApplyDefaultSort);
} private static void PrintData(DataView view) { Console.WriteLine("------"); Console.WriteLine("Filter: {0}",view.RowFilter); Console.WriteLine("State: {0}",view.RowStateFilter); Console.WriteLine("Sort: {0}, Default: {1}",view.Sort,view.ApplyDefaultSort); foreach (DataRowView drv in view) PrintRow(drv); Console.WriteLine("------"); } private static void PrintRow(DataRowView row) { Console.Write("{0}\t",row.RowVersion); foreach (DataColumn col in row.DataView.Table.Columns) Console.Write("{0}\t", row[col.ColumnName]); Console.WriteLine(); }
Notice that we do not have to worry about the row version when using the [] indexing on a DataRowView.
Some code and some output:
Console.WriteLine("Default view from the table itself:");
PrintViewInfo(items.DefaultView);
|
Default view from the table itself: View settings: AllowDelete: True AllowEdit: True AllowNew: True Filter: State: CurrentRows Sort: , Default: False |
DataView view;
view = new DataView(items);
Console.WriteLine("Our view, default settings:");
PrintViewInfo(view);
PrintData(view); |
Our view, default settings: View settings: AllowDelete: True AllowEdit: True AllowNew: True Filter: State: CurrentRows Sort: , Default: False ------ Filter: State: CurrentRows Sort: , Default: False Current 110 freeble teal Current 120 thingie blue Current 130 whatzit blue Current 140 geegaw red Current 150 thingamabob green ------ |
Console.WriteLine("Setting filter and sort:");
view.RowFilter = "color='blue'";
view.RowStateFilter = DataViewRowState.CurrentRows;
view.Sort = "name DESC";
PrintData(view); |
Setting filter and sort: ------ Filter: color='blue' State: CurrentRows Sort: name DESC, Default: False Current 130 whatzit blue Current 120 thingie blue ------ |
Console.WriteLine("You will see a difference between " +
"ModifiedCurrent and ModifiedOriginal");
view.RowFilter = "";
view.Sort = "";
view.RowStateFilter = DataViewRowState.ModifiedCurrent;
PrintData(view);
view.RowStateFilter = DataViewRowState.ModifiedOriginal;
PrintData(view); |
You will see a difference between ModifiedCurrent and ModifiedOriginal |
Console.WriteLine("Look at deleted");
view.RowFilter = string.Empty;
view.RowStateFilter = DataViewRowState.Deleted;
PrintData(view); |
Look at deleted ------ Filter: State: Deleted Sort: , Default: False Original 100 widget blue ------ |
Console.WriteLine("Adding something via the view,"+
" then viewing only added");
DataRowView newRow = view.AddNew();
newRow["color"] = "red";
newRow["name"] = "gadget";
newRow.EndEdit();
view.RowFilter = string.Empty;
view.RowStateFilter = DataViewRowState.Added;
PrintData(view); |
Adding something via the view, then viewing only added ------ Filter: State: Added Sort: , Default: False Current 150 thingamabob green Current 160 gadget red ------ |
Console.WriteLine("Setting ApplyDefaultSort to true "+
"does nothing if sort is set.");
view.RowFilter = string.Empty;
view.RowStateFilter = DataViewRowState.CurrentRows;
view.Sort = "color";
view.ApplyDefaultSort = true;
PrintData(view); |
Setting ApplyDefaultSort to true does nothing if sort is set. ------ Filter: State: CurrentRows Sort: color, Default: True Current 120 thingie blue Current 130 whatzit blue Current 150 thingamabob green Current 140 geegaw red Current 160 gadget red Current 110 freeble teal ------ |
Console.WriteLine("Resetting Sort to empty");
view.ApplyDefaultSort = false;
view.Sort = string.Empty;
PrintData(view); |
Resetting Sort to empty ------ Filter: State: CurrentRows Sort: , Default: False Current 110 freeble teal Current 120 thingie blue Current 130 whatzit blue Current 140 geegaw red Current 150 thingamabob green Current 160 gadget red ------ |
Console.WriteLine("Applying default sort");
view.ApplyDefaultSort = true;
PrintData(view); |
Applying default sort ------ Filter: State: CurrentRows Sort: id, Default: True Current 110 freeble teal Current 120 thingie blue Current 130 whatzit blue Current 140 geegaw red Current 150 thingamabob green Current 160 gadget red ------ |
Console.WriteLine("All current rows, by color");
view.RowFilter = string.Empty;
view.RowStateFilter = DataViewRowState.CurrentRows;
view.ApplyDefaultSort = false;
view.Sort = "color";
PrintData(view); |
All current rows, by color ------ Filter: State: CurrentRows Sort: color, Default: False Current 120 thingie blue Current 130 whatzit blue Current 150 thingamabob green Current 140 geegaw red Current 160 gadget red Current 110 freeble teal ------ |
int index = view.Find("red");
Console.WriteLine("Found first red object at {0}", index); |
Found first red object at 3 |
DataRowView[] rows = view.FindRows("blue");
Console.WriteLine("Blue rows");
foreach (DataRowView drv in rows)
PrintRow(drv.Row); |
Blue rows
120 thingie blue
130 whatzit blue |