I have a query using dynamic pivot, so the column names change based on the data. My code generates a .csv file based on the result of the query. I don't know how I can make the header, as I cannot hard-code column names. Is it possible somehow to make the header of the query result the first row of the recordset?
Thanks.
ADDED: Just realized that I don't even know how to fetch the data in my C# code if I don't know what columns I have... So that I cannot do something like this:
result.AddRange(from DataRow dr in dt.Rows
select new DailyTransactionSheet
{
Serve = Convert.ToInt32(dr["Serve"]),
Remits = Convert.ToInt32(dr["Remits"]),
List = Convert.ToInt32(dr["List"]),
Billing = Convert.ToInt32(dr["Billing"]),
DollarSent = Convert.ToInt32(dr["DollarSent"]),
FileAck = Convert.ToInt32(dr["FileAck"]),
});
}
as per comments:
basically you need to execute query and fetch information about columns form it, depending on how your're executing it, there can be several options:
SQLDataReader to fetch results, you can get column information from GetSchemaTable.Columns GetSchemaTable
or
SqlDataAdapter.Fill(DataSet) DataSet.Tables[0].Columns - these methods and properties you should read about DataSet.Tables
here is example from msdn:
private void PrintRows(DataSet dataSet)
{
// For each table in the DataSet, print the row values.
foreach(DataTable table in dataSet.Tables)
{
foreach(DataRow row in table.Rows)
{
foreach (DataColumn column in table.Columns)
{
Console.WriteLine(row[column]);
}
}
}
}
Related
I'd like to know if there is a way to automatically add columns in a DataTable inside a foreach loop? That is what I mean with "automatically".
I had in mind something like this:
DataTable dt = new DataTable();
foreach (var item in model.Statistik)
{
dt.Columns.Add();
row = dt.NewRow();
row[//Name of column goes here] = // either item or item.property;
dt.Rows.Add(row);
}
This is much more efficient than explicitly name every column before the for each loop. Because, what happens if some property changes or gets deleted, etc.? This is therefore, something I wish to get rid of.
I don't think you understand how dt.Columns and dt.Rows are related. There is one set of Columns for a DataTable. Every Row in the DataTable has all the matching columns - you don't have unique Columns in each Row. So every time you do dt.Columns.Add you are adding a column to every Row, old or new.
Also, how do you expect Row[<name of column>] to work if you don't specify the name to the DataTable?
I have datatable1 which has 11 columns and 100,000 rows.. I would like to do a check to see if the text in column one starts with "one" and if it does, add that row into the second datatable. I have done the below but yet still it does not work.. I get the error that the row belong to another table
foreach (DataRow r in queryDataTable.Rows)
{
if (r[0].ToString().StartsWith(queryString))
{
dt.ImportRow(r);
}
}
You cannot directly import the row of one table into another datatable. You need to create a new row and then copy the row.
Try this -
dt.Rows.Add(r.ItemArray)
Instead of your for loop, you may use LINQ to select those rows which StartsWith queryString and then you can use CopytoDataTable method to create a new table for the selected rows.
var NewTable = queryDataTable.AsEnumerable()
.Where(r => r.Field<string>(0).StartsWith(queryString))
.CopyToDataTable();
Remember to include using System.Linq; at the top.
I want to do this:
public void UpdateDataRowsToDataTable(string tableName, List<DataRow> rows)
{
foreach (DataRow row in rows)
{
// this method does not exist!!
_dataSet.Tables[tableName].Rows.Update(row);
}
}
I need a method that finds a row (maybe by primary key) and updates changed rows to the row in DataTable.
The only possibility what I know is to use Select (or Find) and then maybe iterate all columns and give them new values. Please tell me that this cannot be true!
Although the question is not quite clear it sounds like you have a group of rows from one table and want to update the equivalent rows in another datatable. If this is the case they you can just use the find method and manually update them as you suggested, or alternatively, add the new rows to another table and merge them (there are all sorts of options for merging two data tables). Merging however will just do the same thing under the hood (i.e. find by primary key and update the columns).
Another way would be to just replace the row and set its status to modified datarow.SetModified()
Or you can delete the old one and add the new one...
Could you use boxing to do that if your datatables are the same.
DestDataset.DestDataTable newChildRecords =
(DestDataset.DestDataTable)_dataset.Tables[tableName].GetChanges(DataRowState.Added);
If you are using dataAdapter...
foreach (DataRow row in rows)
{
Row.BeginEdit();
//Do your stuff
Row.EndEdit();
}
dataAdapter.Update(_dataSet, "yourTable");
Another option is to use the ItemArray property to update the DataRow instance. The only thing is that you still have to select the proper rows. Also, note that you have to change the whole ItemArray instead of its elements in order to have the modification reflected in the DataTable.
foreach (DataRow row in rows)
{
// Select the row
var rows = _dataSet.Tables[tableName].Select(string.Format("Table_ID = {0}", row["Table_ID"]));
// Update the row
if (0 < rows.Length)
rows[0].ItemArray = (object[])row.ItemArray.Clone();
}
Regardless of the way you chose to update the DataRow, you can put the whole thing in an extension method.
I have DataTable with the following columns:
ClientID date numberOfTransactions price
ClientID is of type string and I need to ensure that its contents include "A-" and "N6" for every value in the table.
I need to delete all rows from the DataTable where this first column (ClientID) does not contain both "A-" and "N6" (some totals and other unnecessary data). How can I select and delete these rows specifically from the DataTable?
I know this:
foreach (DataRow row in table.Rows) // Loop over the rows.
{
//Here should come part "if first column contains mentioned values
}
I also know this
If (string.Contains("A-") == true && string.Contains("N6") == true)
{
//Do something
}
I need help how to implement this for first column of each row.
Try this:
EDIT: Totally messed up that last line, so if you tried it, try it now that I made it not stupid. =)
List<int> IndicesToRemove = new List<int>();
DataTable table = new DataTable(); //Obviously, your table will already exist at this point
foreach (DataRow row in table.Rows)
{
if (!(row["ClientID"].ToString().Contains("A-") && row["ClientID"].ToString().Contains("N6")))
IndicesToRemove.Add(table.Rows.IndexOf(row));
}
IndicesToRemove.Sort();
for (int i = IndicesToRemove.Count - 1; i >= 0; i--) table.Rows.RemoveAt(IndicesToRemove[i]);
try using this,
assuming dt as your Datatabe object and ClientID as your first column (hence using ItemArray[0])
for(int i=0; i<dt.Rows.Count; i++)
{
temp = dt.Rows[i].ItemArray[0].ToString();
if (System.Text.RegularExpressions.Regex.IsMatch(temp, "A-", System.Text.RegularExpressions.RegexOptions.IgnoreCase) || System.Text.RegularExpressions.Regex.IsMatch(temp, "N6", System.Text.RegularExpressions.RegexOptions.IgnoreCase))
{
dt.Rows.RemoveAt(i);
i--;
}
}
Simple and straight forward solution... hope it helps
this should be more efficient, both in lines of Code and Time, try this :)
for(int x=0; x<table.Rows.Count;)
{
if (!table.Rows[x].ItemArray[0].contains("A-") && !table.Rows[x].ItemArray[0].contains("N6"))
table.Rows.RemoveAt(x);
else x++;
}
Happy Coding
Preface: C.Barlow's existing answer is awesome, this is just another route someone could take.
This is one way to do it where you never have to loop all the way through the original table (by taking advantage of the DataTable.Select() method):
DataTable table = new DataTable(); // This would be your existing DataTable
// Grab only the rows that meet your criteria using the .Select() method
DataRow[] newRows = table.Select("ClientID LIKE '%A-%' AND ClientID LIKE '%N6%'");
// Create a new table with the same schema as your existing one.
DataTable newTable = table.Clone();
foreach (DataRow r in newRows)
{
// Dump the selected rows into the table.
newTable.LoadDataRow(r.ItemArray, true);
}
And now you have a DataTable with only the rows you want. If necessary, at this point you could clear out the original table and replace it with the contents of the new one:
table.Clear();
table = newTable.Copy();
Edit: I thought of a memory optimization last night, you can just overwrite the existing table once you have the rows you need, which avoids the need for the temporary table.
DataTable table = new DataTable(); // This would be your existing DataTable
// Grab only the rows that meet your criteria using the .Select() method
DataRow[] newRows = table.Select("ClientID LIKE '%A-%' AND ClientID LIKE '%N6%'");
// Clear out the old table
table.Clear();
foreach (DataRow r in newRows)
{
// Dump the selected rows into the table.
table.LoadDataRow(r.ItemArray, true);
}
I have two DataTables.
First is
DataTable NameAddressPhones = new DataTable();
with Three columns Name, Address and PhoneNo.But I only want two columns Name and Address data so I want to copy those columns (with data) to the new DataTable.
DataTable NameAddress = new DataTable();
For that I do
foreach (DataRow sourcerow in NameAddressPhones.Rows)
{
DataRow destRow = NameAddress.NewRow();
foreach (string colname in columns)
{
destRow[colname] = sourcerow[colname];
}
NameAddress.Rows.Add(destRow);
}
I clear the NameAddressPhones(first) DataTable every time there are new records inserted in the table. And every time there will be the same number of columns but the column names will be different like Nm instead of Name, Add instead of Address.Now the problem is the second DataTable already has column names Name and Address and now I want to copy the columns data of Nm and Add to the second DataTable but the column names are different than the column names of the second DataTable. So even if there are different column names I want to copy Nm column data of first DataTable to the column Name of second DataTable and column Add data of first DataTable to column Address of second DataTable.
In short how can we copy column data from one DataTable to another even if there are different column names of both DataTables like Nm is the column name of first DataTable and Name is the column name of second DataTable then the data of the column Nm should be copied to the column Name.
Here's the simplest way:
foreach (DataRow sourcerow in NameAdressPhones.Rows)
{
DataRow destRow = NameAdress.NewRow();
destRow["Name"] = sourcerow["Nm"];
destRow["Address"] = sourcerow["Add"];
NameAdress.Rows.Add(destRow);
}
Automation is great when it's available. When it's not, you have to map source columns to destination columns in some manner.
If the columns are in the same order in both tables, you could just reference the values by ordinal instead of column name, but that's such a bad idea I'm not even going to post any code for it.
Use column index number rather than names:
destRow[0] = sourcerow[0]; // for column 0 = "Name" or "NM"
If I've understood your question right, then the way this is usually done is by using stored procedures. You have the same stored procedures in both databases, but the implementation is specific to the table schema of each database. This allows you the abstraction you need.