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 |