Using LINQ Query DataTable using partial column names - c#

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.

Related

Get values of tablerow - dataset Windows CE

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"]);
}

c# datatable select last row on a speicfic condition

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.

ToTable() doesn't return distinct records?

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
.CopyToData‌​Table();
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"]);
}

Linq on DataTable: select specific column into datatable, not whole table

I'm running a LINQ query on a datatable in c#.
I want to select specific columns rather than the whole row and enter the result into a datatable. How can i do that??
My Code:
public DataTable getConversions(string c_to, string p_to)
{
var query = from r in matrix.AsEnumerable()
where r.Field<string>("c_to") == c_to &&
r.Field<string>("p_to") == p_to
select r;
DataTable conversions = query.CopyToDataTable();
If you already know beforehand how many columns your new DataTable would have, you can do something like this:
DataTable matrix = ... // get matrix values from db
DataTable newDataTable = new DataTable();
newDataTable.Columns.Add("c_to", typeof(string));
newDataTable.Columns.Add("p_to", typeof(string));
var query = from r in matrix.AsEnumerable()
where r.Field<string>("c_to") == "foo" &&
r.Field<string>("p_to") == "bar"
let objectArray = new object[]
{
r.Field<string>("c_to"), r.Field<string>("p_to")
}
select objectArray;
foreach (var array in query)
{
newDataTable.Rows.Add(array);
}
Try Access DataTable easiest way which can help you for getting perfect idea for accessing DataTable, DataSet using Linq...
Consider following example, suppose we have DataTable like below.
DataTable ObjDt = new DataTable("List");
ObjDt.Columns.Add("WorkName", typeof(string));
ObjDt.Columns.Add("Price", typeof(decimal));
ObjDt.Columns.Add("Area", typeof(string));
ObjDt.Columns.Add("Quantity",typeof(int));
ObjDt.Columns.Add("Breath",typeof(decimal));
ObjDt.Columns.Add("Length",typeof(decimal));
Here above is the code for DatTable, here we assume that there are some data are available in this DataTable, and we have to bind Grid view of particular by processing some data as shown below.
Area | Quantity | Breath | Length | Price = Quantity * breath *Length
Than we have to fire following query which will give us exact result as we want.
var data = ObjDt.AsEnumerable().Select
(r => new
{
Area = r.Field<string>("Area"),
Que = r.Field<int>("Quantity"),
Breath = r.Field<decimal>("Breath"),
Length = r.Field<decimal>("Length"),
totLen = r.Field<int>("Quantity") * (r.Field<decimal>("Breath") * r.Field<decimal>("Length"))
}).ToList();
We just have to assign this data variable as Data Source.
By using this simple Linq query we can get all our accepts, and also we can perform all other LINQ queries with this…
Here I get only three specific columns from mainDataTable and use the filter
DataTable checkedParams = mainDataTable.Select("checked = true").CopyToDataTable()
.DefaultView.ToTable(false, "lagerID", "reservePeriod", "discount");
LINQ is very effective and easy to use on Lists rather than DataTable. I can see the above answers have a loop(for, foreach), which I will not prefer.
So the best thing to select a perticular column from a DataTable is just use a DataView to filter the column and use it as you want.
Find it here how to do this.
DataView dtView = new DataView(dtYourDataTable);
DataTable dtTableWithOneColumn= dtView .ToTable(true, "ColumnA");
Now the DataTable dtTableWithOneColumn contains only one column(ColumnA).
Your select statement is returning a sequence of anonymous type , not a sequence of DataRows. CopyToDataTable() is only available on IEnumerable<T> where T is or derives from DataRow. You can select r the row object to call CopyToDataTable on it.
var query = from r in matrix.AsEnumerable()
where r.Field<string>("c_to") == c_to &&
r.Field<string>("p_to") == p_to
select r;
DataTable conversions = query.CopyToDataTable();
You can also implement CopyToDataTable Where the Generic Type T Is Not a DataRow.

Sorting the objects of a DataTable collection

I fetch all tables from a database using
tables = Utility.DBConnection.GetSchema("Tables", restrictions);
How do I bring the tables in a alphabetical sort order after?
I checked the GetSchema, there is no property to give any sort order.
I want to do later:
foreach (DataRow row in tables.Rows) {}
But I want to have the tables sorted before.
If tables is a DataTable, you can use the DataTable.DefaultView Property to provide a sorted view into the data:
DataView view = tables.DefaultView;
view.Sort = "Name";
foreach (DataRowView row in view)
{
}
just make an array/list of tables copied from the collection in the dataset, and sort it yourself?
Not sure what Utility.DBConnection.GetSchema returns, but this is probably very close to what you want:
var sortedTables = from table in tables
orderby table.TableName ascending
select table;
You can use a sorted dictionary --
DataTable dtTables = conn.GetSchema("Tables");
SortedDictionary<string, DataRow> dcSortedTables = new SortedDictionary<string, DataRow>();
foreach (DataRow table in dtTables.Rows) {
string tableName = (string)table[2];
dcSortedTables.Add(tableName, table);
}
// Loop through tables
foreach (DataRow table in dcSortedTables.Values) {
// your stuff here
}

Categories