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.
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 following code:
DataTable datTable3 = new DataTable();
datTable3 = datTable1.Clone();
datTable2.Merge(datTable1);
datTable3 = datTable2.GetChanges();
Want I want to do is: Compare DataTable1 with DataTable2 and when there are rows in DataTable1 which aren't in DataTable 2 then add these rows into a new DataTable(3). This code above gives me an empty DataTable3 each time although the rows in the first dt are not equal to the rows in my second dt. what am I doing wrong? Sorry if that question may be too easy but I'm using C# since a couple of months.
EDIT: I found this solution which doesn't work for me... Why?
DataTable datTable3 = new DataTable();
datTable3 = datTable1.Clone();
foreach (DataRow row in datTable1.Rows)
{
datTable3.ImportRow(row);
}
foreach (DataRow row in datTable3.Rows)
{
row.SetAdded();
}
datTable2.Merge(datTable3);
DataTable datTableFinal = datTable2.GetChanges(DataRowState.Added);
// shows me a datatable with again the values from datTable1
// even if they are already in datTable2!
datTable2.RejectChanges();
datTable1.RejectChanges();
The DataTable.GetChanges() method Gets a copy of the DataTable that contains all changes made to it since it was loaded or AcceptChanges was last called.
In other words, GetChanges() is dependent on the DataRow.RowState property. A DataTable.Merge() will either preserve their 'RowState' property, or reset it to 'Unchanged'.
This means that when you merge two DataTables with rows that have 'Unchanged' RowStates, the merged table will also contain 'Unchanged' rows and the DataTable.GetChanges method will return null or Nothing.
EDIT : You can always iterate through the DataTable to see what rows are added to the merged table. Something like
foreach(DataRow row in datTable2.Rows)
{
Console.WriteLine("--- Row ---"); // Print separator.
foreach (var item in row.ItemArray) // Loop over the items.
{
Console.Write("Item: "); // Print label.
Console.WriteLine(item); // Invokes ToString abstract method.
}
}
Iterate through and use LoadDataRow(object[] value, bool fAcceptChanges) :
foreach (DataRow row in MergeTable.Rows)
{
TargetTable.LoadDataRow(row.ItemArray, false);
}
var changes = TargetTable.GetChanges();
changes had the desired value when I tried this method.
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]);
}
}
}
}
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'm trying to figure out where DataRowCollection.Add(DataRow row) inserts the new row into its datatable. Is it at the end of the table, like an append? Is it random?
Also, I want to use this while I'm for looping through a datatable. If some condition exists, add a new row containing different data to run through the For loop to the end of the datatable. Are there any specific problems with this approach? How else might I handle it?
EDIT: I am For Looping through a .Net DataTABLE stored in memory. I'm not touching the dataBASE where the original data is stored during this looping operation. The DataTABLE is populated prior to the loop and is not a problem.
Here is relavant code:
DataTable machineANDlastDate = new DataTable();
//Populate machineANDlastDate
for (int i = 0; i < machineANDlastDate.Rows.Count; i++)
{
lastFutureDate = DateTime.Parse(machineANDlastDate.Rows[i]["MaxDueDate"].ToString());
newDateTime = lastFutureDate.AddDays(frequency); //This is where the new date is created.
machineSerial = machineANDlastDate.Rows[i]["machineSerial"].ToString();
if (newDateTime < DateTime.Now)
{
machineANDlastDate.Rows.Add(new String[] { machineSerial, newDateTime.AddDays(frequency).ToString() });
continue;
}
...Removed for irrelevancy...
}
Is this a valid way to add a row to the end of the datatable?
As far as I know, it is always added to the end of the collection.
If you for loop through the database, there shouldn't be a problem, if you begin at the beginning of the data table and finish at the end of it or smth similar. However, you will then also loop through the newly created data rows, and I don't know whether you want to achieve this. You only could get problems if you take a foreach loop instead because it cannot handle modifications of the underlying collection.
If you want to know if a row is new or not you can check the DataRow.RowState property.
// your code to add rows
...
// process added rows
foreach (DataRow row in machineANDlastDate.Rows)
{
if (row.RowState == DataRowState.Added)
{
// do stuff
}
}
// now confirm new rows (they won't have a RowState of Added after this)
machineANDlastDate.AcceptChanges();
It's always at the end of the table, as far as i know most of the DataBase conectors, whe you use their add row, its always at the end.
The Add method will insert a DataRow into a DataRowCollection object only. To actually add the DataRow to the data table, you will need to call the NewRow method which appends itself onto the DataTable, and thus appends the row to the table in that database. For reference, check out http://msdn.microsoft.com/en-us/library/9yfsd47w.aspx