I have a dataset with a table called "product". this has 3 columns: coding, amount & description.
I want to search a product which I identify by "coding". My Code looks like this:
DataTable table = ds.Tables[0]; // = "Product"
string expression = coding.ToString();
var filtered = table.AsEnumerable()
.Where(r => r.Field<String>("Coding").Equals(expression));
How can I now select for example the matching description for storing it into a variable?
Filtered is not one table row it's a list of table rows. You can iterate throw them and do further operations.
foreach (var row in filtered)
{
Console.WriteLine("{0}, {1}, {2}", row["coding"], row["amount"], row["description"]);
}
Related
I have a datatable has data like this format
........ IVR........
.........IVR........
.........IVR........
.........City1......
.........City1......
.........City1......
.........City2......
.........City2......
.........City2......
I want to take the last row of each value. in order words, the rows that are bold now
The challenge is that i wan these three rows in a datatable. I tried to search on internet but i didn't know what is the name of this feature. could you help me please
You can GroupBy() and then select last row with the help of the Last() method.
var result = from b in myDataTable.AsEnumerable()
group b by b.Field<string>("Your_Column_Name") into g
select g.Last();
DataTable filtered = myDataTable.Clone();
foreach(DataRow row in result)
{
filtered.ImportRow(row);
}
Clone clones the structure of the DataTable, including all DataTable schemas and constraints.
This can be implemented in a simple loop using a Dictionary to hold found rows:
var cRows = new Dictionary<string, DataRow>(StringComparer.InvariantCultureIgnoreCase);
foreach (DataRow oRow in oTable.Rows)
{
var sKey = oRow["KeyValue"].ToString();
if (!cRows.ContainsKey(sKey))
{
cRows.Add(sKey, oRow);
}
else
{
cRows[sKey] = oRow;
}
}
This approach will store the last row for each unique value in the column that you nominate.
To move the selected rows into a new DataTable:
var oNewTable = oTable.Clone();
foreach (var oRow in cRows.Values)
{
oNewTable.Rows.Add(oRow);
}
Clone just clones the structure of the current table, not the rows.
For example my datatable is like this
A_1 A_2 A_3 ..... A_15 B_1.....B_10 C_1....C_10
x y z........ K
1 2 3.........4
I am trying to create seperate datatables for A,B and C which selects the rows based on column prefix, Also i just need row values in my new datatable.
var query = (from dc in table.Columns.Cast<DataColumn>()
where dc.ColumnName.Contains(prefix)
select table.Rows);
If the above is correct, how to proceed to insert the rows(which is in the query) to the new data table ?
You can create a DataView then copy to a DataTable selecting the columns that match your criteria:
string[] cols = (from dc in table.Columns.Cast<DataColumn>()
where dc.ColumnName.Contains(prefix)
select dc.ColumnName)
.ToArray();
DataView view = new DataView(table);
DataTable selected = view.ToTable(false, cols); // false ==> include "duplicate" rows
I have a DataTable with a variable number of columns.
I want to create a LINQ query that returns the data from the columns that start with a 'B_'.
I have a query that returns the columns names that start with 'B_'. It is below:
var arrayNames = (from DataColumn x in stationTable.Columns
where x.ColumnName.Contains("B_")
select x.ColumnName).ToArray();
Now that I have the column names how to I create a query using this array to return the data in the columns?
Thanks
You can create a DataView that hides the columns not in your list - that way you get to keep any type information:
var arrayNames = (from DataColumn x in stationTable.Columns
where !x.ColumnName.Contains("B_") // note the reversal
select x.ColumnName).ToArray();
DataView dv = new DataView(stationTable);
foreach (string colName in arrayNames)
dv.Table.Columns[colName].ColumnMapping = MappingType.Hidden
There are a couple of ways to approach this.
If you don't care about grouping the items by column type, this query accomplishes that:
var query = from DataColumn col in stationTable.Columns
from DataRow row in stationTable.Rows
where col.ColumnName.StartsWith("B_")
select row[col.ColumnName];
However, to maintain the grouping, you could use a lookup as follows:
var query = (from DataColumn col in stationTable.Columns
from DataRow row in stationTable.Rows
where col.ColumnName.StartsWith("B_")
select new { Row = row[col.ColumnName], col.ColumnName })
.ToLookup(o => o.ColumnName, o => o.Row);
foreach (var group in query)
{
Console.WriteLine("ColumnName: {0}", group.Key);
foreach (var item in group)
{
Console.WriteLine(item);
}
}
The downside of either approach is you're ending up with an object. Retaining the results in a strongly typed manner would require some extra work given the dynamic nature of the question.
I am using datatable to return me distinct records but somehow its not returning me distinct records
I tried like
dt.DefaultView.ToTable(true, "Id");
foreach (DataRow row in dt.Rows)
{
System.Diagnostics.Debug.Write(row["Id"]);
}
It still returns me all the records. What could be wrong here?
UPDATE
My sql is as below
select t.Update ,t.id as Id, t.name ,t.toDate,t.Age from tableA t Where t.Id = 55
union
select t.Update ,t.id as Id, t.name ,t.toDate,t.Age from tableB t Where t.Id = 55
order by Id
Its very hard to do distinct in my query as there are many columns than mentioned here.
If you use a database it would be better to use sql to return only distinct records(e.g. by using DISTINCT, GROUP BY or a window function).
If you want to filter the table in memory you could also use Linq-To-DataSet:
dt = dt.AsEnumerable()
.GroupBy(r=>r.Field<int>("Id")) // assuming that the type is `int`
.Select(g=>g.First()) // take the first row of each group arbitrarily
.CopyToDataTable();
Note that the power of Linq starts when you want to filter these rows or if you don't want to take the first row of each id-group arbitrarily but for example the last row(acc. to a DateTime field). Maybe you also want to order the groups or just return the first ten. No problem, just use OrderBy and Take.
The issue is that you're not grabbing the new table:
var newDt = dt.DefaultView.ToTable(true, "Id");
foreach (DataRow dr in newDt.Rows) ...
the ToTable method doesn't modify the existing table - it creates a new one.
DataView view = new DataView(table);
DataTable distinctValues = view.ToTable(true, "Id");
you are not assigning the return value to any variable, try this
DataTable dtnew = dt.DefaultView.ToTable(true, "Id");
foreach (DataRow row in dtnew.Rows)
{
System.Diagnostics.Debug.Write(row["Id"]);
}
I have two tables:
tbl_ClassFac:
ClassFacNo (Primary Key)
,FacultyID
,ClassID
tbl_EmpClassFac:
EmpID, (Primary Key)
DateImplement, (Primary Key)
ClassFacNo
I want to know all the Employees who are on a specific ClassFacNo. ie. All EmpID with a specific ClassFacNo... What I do is that I first search tbl_EmpClassFac with the EmpID supplied by the user. I store these datarows. Then use the ClassFacNo from these datarows to search through tbl_ClassFac.
The following is my code.
empRowsCF = ClassFacDS.Tables["EmpClassFac"].Select("EmpID='" + txt_SearchValueCF.Text + "'");
int maxempRowsCF = empRowsCF.Length;
if (maxempRowsCF > 0)
{
foundempDT = ClassFacDS.Tables["ClassFac"].Clone();
foreach (DataRow dRow in empRowsCF)
{
returnedRowsCF = ClassFacDS.Tables["ClassFac"].Select("ClassFacNo='" + dRow[2].ToString() + "'");
foundempDT.ImportRow(returnedRowsCF[0]);
}
}
dataGrid_CF.DataSource = null;
dataGrid_CF.DataSource = foundempDT.DefaultView;
***returnedRowsCF = foundempDT.Rows;*** // so NavigateRecordsCF can be used
NavigateRecordsCF("F"); // function to display data in textboxes (no importance here)
I know the code is not very good but that is all I can think of. If anyone has any suggestions please please tell me. If not tell me how do I copy all the Rows in a datatable to a datarow array ???
"How to copy all the rows in a datatable to a datarow array?"
If that helps, use the overload of Select without a parameter
DataRow[] rows = table.Select();
DataTable.Select()
Gets an array of all DataRow objects.
According to the rest of your question: it's actually not clear what's the question.
But i assume you want to filter the first table by a value of a field in the second(related) table. You can use this concise Linq-To-DataSet query:
var rows = from cfrow in tbl_ClassFac.AsEnumerable()
join ecfRow in tbl_EmpClassFac.AsEnumerable()
on cfrow.Field<int>("ClassFacNo") equals ecfRow.Field<int>("ClassFacNo")
where ecfRow.Field<int>("EmpId") == EmpId
select cfrow;
// if you want a new DataTable from the filtered tbl_ClassFac-DataRows:
var tblResult = rows.CopyToDataTable();
Note that you can get an exception at CopyToDataTable if the sequence of datarows is empty, so the filter didn't return any rows. You can avoid it in this way:
var tblResult = rows.Any() ? rows.CopyToDataTable() : tbl_ClassFac.Clone(); // empty table with same columns as source table