I am having trouble sorting a dataset that is merged in the wrong order. Here is the code:
// Adding new data to DataSet ds:
DataSet dsNew = messageSearcher.Seek(_CriteriaCollection.ToString(), mb.ConvertedClassId, mb.ConnectionString); // Recieving a set of ID that are new and need to be added to ds
ds.Merge(dsNew);
// The data set is now sorted wrongly. Therefore want to sort it based on "MME_ID"
var table = ds.Tables[0];
var view = new DataView(table);
var newRows = view.DeepCopy();
newRows.Sort = "MME_ID DESC"; // <--- This does not sort the ResultSet... Why?
table.Rows.Clear();
foreach (var row in newRows)
table.Rows.Add(row);
ds.AcceptChanges();
What am I doing wrong?
A view is just a view, DataView.Sort will not sort the underlying DataTable. I would suggest to use Linq-To-DataSet instead which is more readable and maintainable:
var table = ds.Tables[0].AsEnumerable()
.OrderByDescending(row => row.Field<int>("MME_ID"))
.CopyToDataTable();
Note that i've presumed that MME_ID is an int column. This throws an exception if its a different type like string. Then you eother have to change the Field<T> to use the proper type or - if you want to order numerically instead of lexicographically - parse it to int with int.Parse.
Related
I have a DataTable(dataTable1) that have 25-30 columns. I want to bind a DataGridView by creating a small DataTable (dataTable2) that will have few columns (may 5-10) from the existing DataTable.
So my main task is to create a DataTable with fewer columns from the existing one.
Here is the code what I have tried so for..
DataTable subDataTable()
{
DataTable smallTable=new DataTable();
smallTable =dataTable1;// dataTable1 is already filled with data
smallTable.Columns.Remove("Column2");
smallTable.Columns.Remove("Column5");
smallTable.Columns.Remove("Column6");
smallTable.Columns.Remove("Column13");
smallTable.Columns.Remove("Column16");
return smallTable;
}
Its working fine. But I'm looking if there any better way.
You can try to convert your DataTable to IEnumerable,and Select necessary fields with linq like this:
var myValues = dataTable1.AsEnumerable()
.Select(x => new { col1 = x["Column1"], col2 = x["Column2"]..});
dataGridView.DataSource = myValues;
Your code will not work because you all you do is assign a variable smallTable with reference to dataTable1 and you removing columns from your original table object
Linq is faster to write but here is what you want to do to understand your issue:
DataTable smallTable = dataTable1.Clone(); // Copy data structure
// Now you can remove your columns
smallTable.Columns.Remove("Column2");
......
foreach (var row in dataTable1.Rows) // iterate all rows
{
var newRow = smallTable.NewRow();
foreach (var col in smallTable.Columns) // and iterate only needed columns
{
newRow[col.ColumnName] = row[col.ColumnName];
}
}
This is pretty much what sugar-coated by Linq
DataView dv = new DataView(dataTable1);
DataTable smallTable = dv.ToTable(true, new string[] { "Column2", "Column5"...});
https://social.msdn.microsoft.com/Forums/en-US/ac2c7c95-66d6-4db6-a6fb-4dccd5fa701e/is-there-a-better-way-to-get-subtable-with-selected-columns-of-a-datatable?forum=adodotnetdataset
Tomer.
I have a DataSet with many DataTables each containing many columns plus a column buildingID.
I would like to filter the entire DataSet by giving it a value for buildingID. I would like the rows in every table with a buildingID of, say 343.
Is there any quick possible way in C#?
You can use DataTable.Select, which returns filtered rows from a DataTable matching a criteria.
foreach (DataTable table in dataset.Tables) {
var rows = table.Select("buildingID = " + buildingId.ToString());
// Do stuff with filtered rows
}
To easily get all the rows that match your criteria, here's a LINQ expression:
var rows = dataset.Tables.SelectMany(
t => t.Select("buildingID = " + buildingId.ToString()));
What about this?
var ds1 = new DataSet();
foreach (DataTable dt in ds1.Tables)
{
var filtereddt = dt.AsEnumerable().Where(row => row.Field<int>("buildingID") == 1).ToList();
//you can add these lists to another list array or something like that.
}
Let's say I have a table with a Color column. Color can have various values. I have a C# method that can handle items of a given column at a time. Thus, I would like to :
foreach(colorname in mytable.getDistinctColornames)
monocolorMethod(mytable.getSubTableOnlyContainingRowsWithColor(colorname))
How would I do that elegantly ... ?
At all prices, I would avoid copying the data back & forth. I would like kind of a view on the datatable. A view that would only "show" the rows of a given columns, and a "writable" view (i.e. when I write to the filtered subset, the original table is written to)
EDIT :
Let's say I have a 'Car' Table, and I would like to replace 'Sedan' by 'Truck' in column 'Type' for all cars with 'Color=Red'.
How would I do given the following code ?
DataTable cars (...); // the data
DataView dv = cars.DefaultView;
dv.RowFilter = "Color='Red'";
< Here I would like to loop on the DataView>. The following code does not work :
foreach (row in dv.AsEnumerable)
{
if(row["Type"] == "Sedan")
row["Type"] = "Truck";
}
EDIT 2 :
Found this http://msdn.microsoft.com/fr-fr/library/system.data.dataview.allowedit.aspx which suggests
view.AllowEdit = true;
view[0].BeginEdit();
view[0]["FirstName"] = "Mary";
view[0]["LastName"] = "Jones";
view[0].EndEdit();
Check out this:
Querying DataSets – Introduction to LINQ to DataSet
Did you try using DataView class? It looks like exactly what you want to achieve without using LINQ: http://msdn.microsoft.com/en-us/library/fdcwwhez
An example of usage:
Let say there is a DataTable object named _dt with 4 rows in it:
_dt = new DataTable("") {Columns = {new DataColumn("ID"), new DataColumn("Name"), new DataColumn("Order")}};
_dt.Rows.Add(1, "one", 1);
_dt.Rows.Add(2, "two", 3);
_dt.Rows.Add(3, "three", 2);
_dt.Rows.Add(4, "four", 5);
You can easily create DataView which doesn't filter data but perform sorting operation on it:
_dv = new DataView(_dt, "", "Order, Name", DataViewRowState.CurrentRows);
You can also add new rows into the DataView and because it is set on corresponding DataTable that new row will be added directly to _dt object. The sorting order will be updated as well, and new row won't be the last one within the DataView (because sort is done on Order and Name columns)
var newRow = _dv.AddNew();
newRow["ID"] = 5;
newRow["Name"] = "five";
newRow["Order"] = 4;
newRow.EndEdit();
After that code there will be 5 rows in _dt. Editing rows is also quite simple:
var editedRow = _dv[0];
editedRow.BeginEdit();
editedRow["Name"] = "Test";
editedRow.EndEdit();
You can also use DataView.Find() or DataView.FindRows() methods to find a row within the DataView.
How to get the Selected columns form the DataTable? For e.g my BaseTable has three columns, ColumnA, ColumnB and ColumnC. Now as part of intermediate operations, I need to retrieve all the rows only from the ColumnA. Is there any predefined formula just like DataTable.Select?
DataView.ToTable Method.
DataView view = new DataView(MyDataTable);
DataTable distinctValues = view.ToTable(true, "ColumnA");
Now you can select.
DataRow[] myRows = distinctValues.Select();
From this question: How to select distinct rows in a datatable and store into an array you can get the distinct values:
DataView view = new DataView(table);
DataTable distinctValues = view.ToTable(true, "ColumnA");
If you're dealing with a large DataTable and care about the performance, I would suggest something like the following in .NET 2.0. I'm assuming the type of the data you're displaying is a string so please change as necessary.
Dictionary<string,string> colA = new Dictionary<string,string>();
foreach (DataRow row in table.Rows) {
colA[(string)row["ColumnA"]] = "";
}
return colA.Keys;
I have a DataTable with data loaded from an external source, one of the column is an int.
I'd like to add a column to the DataTable, containing a description of that int.
I have a Dictionary, or in some cases something like:
Pair<int,string> mapping_values[] = {
new Pair<String, int>("start", 3),
new Pair<String, int>("end", 6),
... etc.
};
The DataTable contains a "status_value", an integer which maps to the int in mapping_values
DataTable tbl = ...;
tbl.Columns.add("Status Text",typeof(string));
Now, I'd like to fill the values of this new Status Text column with
the string from mapping_values where tbl["status_value"] matches the integer (3 or 6 in this case) and fill in "start" or "end". Can linq help me here, or something else ?
You'll need to manually populate the column in a loop.
To do that, you should put your mapping in a dictionary.
For example:
var mapping = mapping_values.ToDictionary(p => p.Value1, p => p.Value2);
foreach(DataRow row in table.Rows)
row["Status Text"] = mapping[row.Field<int>("Status Value")];