Targeting a specific column in a DataRow - c#

I'm trying to perform the C# equivalent of Select * where [columnname] = [value]. I began with a foreach loop to iterate through the table row by row, however I had forgotten that one cannot access a column via row.column["<colname>"].
How do I achieve this objective? Most of the examples I have seen target one specific row with the intention of casting it's value to a string, however my task is to move all entries with a value of DateTime == < DateTime.Today to an archived table.
Can I continue with the following code? Or am I approaching this in the wrong manner?
void archiveDates()
{
foreach (DataRow row in workingupdates.storageTable.Rows)
{
//target DateTime column here
}
}

You can use the Field extension method that is strongly typed and also supports nullable types. You have an overload for the index, name or the DataColumn(among others):
foreach (DataRow row in workingupdates.storageTable.Rows)
{
DateTime dt = row.Field<DateTime>("columnname");
}
If you instead want to find all rows where the date column has a specific value you can use Linq-To-DataTable:
var matchingDataRows = workingupdates.storageTable.AsEnumerable()
.Where(row => row.Field<DateTime>("columnname") == dateTimeVariable);
Now you can simply enumerate this query:
foreach (DataRow row in matchingDataRows)
{
// ...
}
Or create a collection like
a DataRow[] with matchingDataRows.ToArray() or
a List<DataRow> with matchingDataRows.ToList()
a new DataTable with matchingDataRows.CopyToDataTable()
Note that you have to add System.Linq; to the top of the file.

Related

How to replace double quotes of all rows of DataTable using Linq in C#? [duplicate]

This question already has answers here:
Remove Single Quotes From All Cells in a DataTable - Creating New Table - Using LINQ in Vb.Net
(2 answers)
Closed 3 years ago.
How to replace double quotes of all rows of DataTable using Linq in C#?
I tried below but I need more optimized code for same purpose
int columnIndex = 0;
dtExcelData.Rows.RemoveAt(0);
foreach (DataColumn excelSheetColumns in dtExcelData.Columns)
{
int rowIndex = 0;
foreach (DataRow row in dtExcelData.Rows)
{
dtExcelData.Rows[rowIndex][columnIndex] = dtExcelData.Rows[rowIndex][columnIndex].ToString().Replace("\"", "");
rowIndex++;
}
columnIndex++;
}
Please suggest
You could make use of DataRow.ItemArray. For example
foreach(var row in dtExcelData.Rows.Cast<DataRow>())
{
row.ItemArray = row.ItemArray.Select(x=>x.ToString().Replace("\"","")).ToArray();
}
You should
be aware you remove the first row, if you write results back to your data store you will lose this row.
ask yourself why you iterare over Columns and rows if you never use the objects. Why don't you simply use a for loop over rowIndex and columnIndex.
think about only processing data fields that really are a string.ToString() turns everything into a string, then you overwrite any kind of data field type with a string. Better test for "is String" and then cast the field into (String).
think about getting every row, then process every column in this row. This could be faster to execute, but even if it isn't then still is more understandable (at least to me).
I have added code here because code is better other than URL, You can try this below code:
That is already mentioned in below URL
Remove Single Quotes From All Cells in a DataTable - Creating New Table - Using LINQ in Vb.Net
dtExcelData.Rows.RemoveAt(0);
DataTable clone = dtExcelData.Clone();
string t;
var qry = from DataRow row in dtExcelData.Rows
let arr = row.ItemArray
select Array.ConvertAll(arr, s =>
(t = s as string) != null
&& t.StartsWith("\"")
&& t.EndsWith("\"") ? t.Trim('\"') : s);
foreach (object[] arr in qry)
{
clone.Rows.Add(arr);
}

How to get Column Names using Linq from DataTable

I'm trying to use LINQ on DataTable that's getting it's data from sql. So I have a data table with it's usual columns and rows and it appears exactly like a sql select statement. Now I need to get certain rows and columns (including column names) from this data.
I converted the datatable to something LINQ can use using AsEnumerable but I'm not sure what exactly it does. Does it convert the data into an array of objects where each row becomes an object?
I'm used to working with Javascript and it's newer arrow functions so i'd like to use Linq with lambda to keep it consistent.
I'm trying to get rows and column names where first column has a value equal to 2018
DataTable myTable = getData(); // populates the datatable and I've verified the data
var linqTable = myTable.AsEnumerable().Select( x => x[0] = 2018);
I need to get the rows and column names. e.g like an object or array of objects.However, the code above doesn't return the data or column names but just two rows with 2018 in it.
My goal is to eventually serialize this data as json and send it to web page.
To Get the column names:
myTable.Columns.Cast<DataColumn>().Select(dc =>dc.ColumnName).ToList();
The problem is Select() is projecting the objects into a new form. You are seeing 2018 because of '=' instead of '=='. You need to use Where()
var linqTable = myTable.AsEnumerable().Where( x => x.Field<int>(0) == 2018);
You will still end up with a list of DataRows though. The DataTable object isn't really what you should be using because it already provides a nice way to filter its rows:
myTable.Rows.Find(2018);
If you are trying to convert it to a list of objects you should use the Select() method something like:
var linqTable = myTable.AsEnumerable().Where(x => x.Field<int>(0) == 2018)
.Select(x => new
{
year = x[0],
p1 = x[1],
p2 = x[2] // etc...
});
You can create the following function:
public static DataTable CreateDataTableFromAnyCollection<T>(IEnumerable<T> list)
{
Type type = typeof(T);
var properties = type.GetProperties();
DataTable dataTable = new DataTable();
foreach (PropertyInfo info in properties)
{
dataTable.Columns.Add(new DataColumn(info.Name, Nullable.GetUnderlyingType(info.PropertyType) ?? info.PropertyType));
}
foreach (T entity in list)
{
object[] values = new object[properties.Length];
for (int i = 0; i < properties.Length; i++)
{
values[i] = properties[i].GetValue(entity,null);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
and pass any type of object your LINQ query returning.
DataTable dt = CreateDataTableFromAnyCollection(query);
I hope this will help you.
Creating a DataTable From a Query (LINQ to DataSet)

The given DataRow is not in the current DataRowCollection when tried move item from DataGridView to another

I have two DataGridView like this:
Button selected will move DataRow of DataGridView to another DataGridView.
My code like this:
public static DataRow[] GetSelectedDataRows(DataGridView grid)
{
DataRow[] dRows = new DataRow[grid.SelectedRows.Count];
for (int i = 0; i < grid.SelectedRows.Count; i++)
dRows[i] = ((DataRowView)grid.SelectedRows[i].DataBoundItem).Row;
return dRows;
}
public void MoveRows(DataTable src, DataTable dest, DataRow[] rows)
{
foreach (DataRow row in rows)
{
// add to dest
dest.Rows.Add(row.ItemArray);
// remove from src
src.Rows.Remove(row);
}
}
I use it in Event btnMoveToRight_Click().
MoveRows(dtUser, dtUserStop, GetSelectedDataRows(dgvUser));
It throws exception error like:
The given DataRow is not in the current DataRowCollection
at line:
src.Rows.Remove(row);
You can't change the Table field of a DataRow.
So you need to create a new row and also copy the data separately, maybe like this:
public void MoveRows(DataTable src, DataTable dest, DataRow[] rows)
{
foreach (DataRow row in rows)
{
// create empty row
DataRow newrow = dest.NewRow();
// copy data
newrow.ItemArray = row.ItemArray;
// add to dest
dest.Rows.Add(newrow); // (*)
// remove from src NOTE: This may or may not throw an RowNotInTableException
// to avoid it you can skip the Remove and use the loop below instead..
src.Rows.Remove(row);
}
// alternative way of removing the rows..
//foreach (DataGridViewRow item in this.dgvUser.SelectedRows)
//{
// dgvUser.Rows.RemoveAt(item.Index);
//}
}
(*) An even shorter way to clone a DataRow is using this overload of the Add method:
dest.Rows.Add(row.ItemArray);
No need for the newrow now. Note that you may want to copy the RowState from the old to the new row!? See here and here for examples of changing the RowState
If you find you need to remove the DataRows via removing the DataGridViewRows you should add the DGV to the parameters of the MoveRows function to avoid an unecessary dependence..!
Of course this assumes that the DataTables have the same structure, maybe because one is a (structural) clone of the other:
dest = src.Clone();
DataRow has a DataTable property on it (DataRow.Table).
This leads me to think that adding the row to a new table breaks the association with the old DataTable, so you don't need to call src.Rows.Remove(row).

Ultrawingrid - Select row based on unique value

Is there a way to select a row in an ultrawingrid based on the value of one of its columns (ID column)? I have been trying to find out how to do this with little success.
I have a global variable that is the 'active ID' (i.e the ID that is currently being edited within the application - it is the ID that the system sees as being selected and active) - but sometimes the selected row of the grid and the 'selected ID' variable don't match. I need to make sure they are the same in order to prevent user confusion. I am hoping to call the following code inside a refresh() function...
Perhaps something like (kinda-pseudo-code-ish):
int index; // This could be any number
foreach (row r in grid)
{
if (row.cell["ID"].value = index)
grid.selectedindex = thisRow;
}
Am I thinking along the right lines? If so, what is the correct syntax? If not, how else should I do this?
Got it.
int index;
foreach (UltraGridRow row in grid.Rows)
{
if (Convert.ToInt32(row.Cells["ID"].Value) == index)
{
grid.ActiveRow = row;
break;
}
}
Works just how I needed it to - sorry for answering my own question ;)
Yes. You can use the FirstOrDefault function to find a row matching a criteria:
var row = ultraGrid1.Rows.FirstOrDefault(r => r.Cells["Id"].Value.ToString() == "1");
Now that you (potentially) have the row where the cell contains the value you'd like, you can activate it to select it:
if (row != null)
row.Activate();
If you are bound to a DataTable or a list that has the ability to find an item by key, you can use the GetRowWithListIndex method of the Rows collection to find the UltraGridRow.
For example the following will activate the row with a key of 5:
DataTable dt = this.ultraGrid1.DataSource as DataTable;
DataRow dr = dt.Rows.Find(5);
this.ultraGrid1.Rows.GetRowWithListIndex(dt.Rows.IndexOf(dr)).Activate();
If your list doesn't support finding an item by key, you could use linq to find the item in the list as well. There is an example of finding an item with link here.
If you have multiple bands you can use the following:
int index;
ultraGrid1.DisplayLayout.Bands.OfType<Infragistics.Win.UltraWinGrid.UltraGridBand>()
.SelectMany(s => s.GetRowEnumerator(Infragistics.Win.UltraWinGrid.GridRowType.DataRow)
.OfType<Infragistics.Win.UltraWinGrid.UltraGridRow>())
.Where(s => s.Cells.Exists("ID"))
.FirstOrDefault(s => (int)s.Cells["ID"].Value == index)?
.Activate();
Note: Null-conditional Operator (?) requires C# 6.0 or higher. Otherwise you have to check, if FirstOrDefault(...)!=null and activate it then.

Best practice when converting DataColumn values to an array of strings?

Best practice when converting DataColumn values to an array of strings?
[Edit]
All values for certain DataColumn for all DataTable rows to be converted to an array of string?
If I understood your goal you want to specify a particular column and return all its values as a string array.
Try these approaches out:
int columnIndex = 2; // desired column index
// for loop approach
string[] results = new string[dt.Rows.Count];
for (int index = 0; index < dt.Rows.Count; index++)
{
results[index] = dt.Rows[index][columnIndex].ToString();
}
// LINQ
var result = dt.Rows.Cast<DataRow>()
.Select(row => row[columnIndex].ToString())
.ToArray();
You could replace columnIndex with columnName instead, for example:
string columnName = "OrderId";"
EDIT: you've asked for a string array specifically but in case you're flexible about the requirements I would prefer a List<string> to avoid the need to determine the array length prior to the for loop in the first example and simply add items to it. It's also a good opportunity to use a foreach loop instead.
I would then rewrite the code as follows:
List<string> list = new List<string>();
foreach (DataRow row in dt.Rows)
{
list.Add(row[columnIndex].ToString());
}
DataRow.ItemArray Property -
http://msdn.microsoft.com/en-us/library/system.data.datarow.itemarray.aspx
Also, which version are you using? You should check out the DataTableExtensions class -
http://msdn.microsoft.com/en-us/library/system.data.datatableextensions.aspx
And the DataRowExtensions class -
http://msdn.microsoft.com/en-us/library/system.data.datarowextensions.aspx
I know this question is old, but I found it in my Google search trying to do something similar. I wanted to create a list from all the values contained in a specific row of my datatable. In my code example below, I added a SQL datasource to my project in Visual Studio using the GUI wizards and I dropped the needed table adapter into the designer.
'Create a private DataTable
Private authTable As New qmgmtDataSet.AuthoritiesDataTable
'Fill the private table using the table adapter
Me.AuthoritiesTableAdapter1.Fill(Me.authTable)
'Make the list of values
Dim authNames As List(Of String) = New List(Of String)(From value As qmgmtDataSet.AuthoritiesRow In Me.authTable.Rows Select names.authName)

Categories