Finding row index of a row within the original datatable - c#

I have a datatable that I fill with data
DataTable data = new DataTable();
FillData(data);
The datatable gets modified on the go and I capture the modified data so I can save it in a DB:
DataTable changes = data.GetChanges();
I use data from the changes DataTable and save it into DB, the query I use returns an INT id that I need to save into the original data DataTable. How can I get corresponding index in the data table basig on the changes table?

I used to intersect to get intersection of data table and changes table
public void intersect(DataTable data, DataTable changes)
{
var changeIds = data.AsEnumerable().Intersect(changes.AsEnumerable(), DataRowComparer.Default);
foreach (DataRow row in changeIds)
{
Response.Write(row["Id"]);
}
}

Related

Populate DataTable from other smaller DataTables

I have an async operation will goes out and populates a DataTable with some parameters and it's repeated a couple of times, so each time it goes out it will get a DataTable.
I want to save each of these smaller DataTables into a larger DataTable. I'm trying this where DataTable table is the table which represents the smaller Datatable and dtMain is the larger DataTable. I have this in a loop and each iteration, the table should copy over its Rows into dtMain:
DataTable table = await SomeOperationWhichReturnsADataTable();
DataTable dtMain;
if (dtMain.Rows.Count == 0) // Copy over Rows and Columns since dtMain is empty
{
dtMain = table.Copy();
}
else
{
foreach (DataRow dataRow in table.Rows) // Just copy the Rows
{
dtMain.Rows.Add(dataRow.ItemArray);
}
}
}
Is there a better way to do this other than just Copying the Rows over for each table?
Have you tried using the DataTable Merge method? i believe you can change your code to something like this:
DataTable table = await SomeOperationWhichReturnsADataTable();
DataTable dtMain;
/*Not sure about this validation as no information about dsActv
was provided so i will leave it as is*/
if (dsActv.Rows.Count == 0) // Copy over Rows and Columns
{
dtMain= table.Copy();
}
else
{
dtMain.Merge(table);
}

DataTable.Clear() method affect detached row

I'm trying to do something like this to create copy of a typed datarow:
var desRow = dataTable.NewRow();
var sourceRow = dataTable.Rows[rowNum];
desRow.ItemArray = sourceRow.ItemArray.Clone() as object[];
But when I call dataTable.Clear() method it clears all fields in desRow. How to create a deep copy of a DataRow?
In your code when you create your new row you create with that row a reference to the dataTable and that is why it clears all fields.
You can work with a data table clone, that way you will have a deep copy.
DataTable dt = ...
DataTable cloneDt = dt.Clone();
DataRow row = cloneDt.Rows[number];
dt.Rows.Clear();
dt.Rows.Add(row);
This way you will have your original data table with only the selected row.

Update a single row in DataTable

tl;dr:
I want to update ONE DataTable row and then re-cache this whole DataTable(The DataTable not just the row) so I can use it later on
I'm using a cache to store a large DataTable that I've filled with a SqlAdapter based on my MSSQL database
I use this cache to get the DataTable then use it to display a table inside a webpage, nothing odd here.
But this DataTable contains a list of users and I want to be able to edit these users(edit them in the MSSQL database that is) which is easy to do.
The issue is that after each SQL Update you have to re-cache the DataTable(otherwise it'll only be updated in the database but not in the DataTable/webpage) and since it is very large it's very annoying and makes the very simple user update take a very long time since it'll also have to a SQL SELECT to get all posts and then re-cache it
Because of this I want to update that specific row in the DataTable directly after doing my SQL update, this way I don't have to re-fetch the whole SQL table (It is the SQL SELECT part that takes a while since it is so large)
So far I've done this
//We just updated our user, now we'll fetch that with SQL and put it in a new fresh DataTable(that contains just that one row) - since this is much faster than getting the whole table
//Then we'll use that DataTable containing one fresh row to update our old DataTable and re-cache it
DataTable newDataTable = getUserByID(userID); //Get our just edited DataTable row
DataTable cachedDataTable = getSetUserCache(); //Get our cached DataTable
DataRow oldRow = cachedDataTable.Select(string.Format("id = {0}", userID)).FirstOrDefault(); //Get the old row that contains the correct ID
string test = oldRow["status"].ToString(); //Contains the old and cached value before it got edited
oldRow = newDataTable.Rows[0]; //Update the old row with the new row
string test2 = oldRow["status"].ToString(); //Now it contains the new edited value
//Here I should update the cachedDataTable with the new row updated row
DataRow oldRowAfterUpdated = cachedDataTable.Select(string.Format("id = {0}", userID)).FirstOrDefault(); //Get the old row that now should be updated but isn't
string test3 = oldRowAfterUpdated["status"].ToString(); //Still contains the old and cached value before it got edited
success = updateUserCache(cachedDataTable); //Update the DataTable cache that we'll be using later on
I only see posts on how you update the rows, but how do you actually update the DataTable itself with the new row?
Solution :
cachedDataTable.Select(string.Format("id = {0}", userID)).FirstOrDefault().ItemArray = newDataTable.Rows[0].ItemArray;
I think that you may use ItemArray property of DataRow:
void Main()
{
DataTable tableOld = new DataTable();
tableOld.Columns.Add("ID", typeof(int));
tableOld.Columns.Add("Name", typeof(string));
tableOld.Rows.Add(1, "1");
tableOld.Rows.Add(2, "2");
tableOld.Rows.Add(3, "3");
DataTable tableNew = new DataTable();
tableNew.Columns.Add("ID", typeof(int));
tableNew.Columns.Add("Name", typeof(string));
tableNew.Rows.Add(1, "1");
tableNew.Rows.Add(2, "2");
tableNew.Rows.Add(3, "33");
tableOld.Rows[2].ItemArray = tableNew.Rows[2].ItemArray; //update specific row of tableOld with new values
//tableOld.Dump();
}

Enumerate over DataTable, filter items, then revert to DataTable

I'd like to filter items in my DataTable by whether a column value is contained inside a string array by converting it to an IEnumerable<DataRow>, afterwards I'd like to re-convert it to DataTable since that's what my method has to return.
Here's my code so far:
string[] ids = /*Gets string array of IDs here*/
DataTable dt = /*Databasecall returning a DataTable here*/
IEnumerable<DataRow> ie = dt.AsEnumerable();
ie = ie.Where<DataRow>(row => ids.Contains(row["id"].ToString()));
/*At this point I've filtered out the entries I don't want, now how do I convert this back to a DataTable? The following does NOT work.*/
ie.CopyToDataTable(dt, System.Data.LoadOption.PreserveChanges);
return dt;
I would create an empty clone of the data table:
DataTable newTable = dt.Clone();
Then import the rows from the old table that match the filter:
foreach(DataRow row in ie)
{
newTable.ImportRow(row);
}
Assuming that you want to filter the rows in-place, that is the filtered rows should be returned in the same DataTable that was created through the original database query, you should first clear the DataTable.Rows collection. Then you should copy the filtered rows to an array and add them sequentially:
ie = ie.Where<DataRow>(row => ids.Contains(row["id"].ToString())).ToArray();
dt.Rows.Clear();
foreach (var row in ie)
{
dt.Rows.Add(row);
}
An alternative way to achieve this could be to simply iterate through the rows in the DataTable once and delete the ones that should be filtered out:
foreach (var row in dt.Rows)
{
if (ids.Contains(row["id"].ToString()) == false)
{
row.Delete();
}
}
dt.AcceptChanges();
Note that if the DataTable is part of a DataSet that is being used to update the database, all modifications made to the DataTable.Rows collection will be reflected in the corresponding database table during an update.

asp.net copying row from one datatable to another

i have a datable and like this i have searched a datarow from the datable on the basis of some primary now i want to add that searched row to another datatable how can i achieve this please let me know
DataTable findRows = (DataTable)ViewState["dt"];
List<int> selectedList=(List<int>)ViewState["selectedList"];
DataTable temp = new DataTable();
foreach (int id in selectedList)
{
DataRow dr=findRows.Rows.Find(id);
}
now i want it to add to datatable temp how can i achieve this?
First, when creating temp don't just instantiate it as a new DataTable but instead call .Clone() on findrows to create a structurally identical DataTable.
Second, use .ImportRow() on the second DataTable and pass it the row from the first DataTable that you'd like to copy. This should create an entirely new row in the second table with the same values as the row from the first table.

Categories

Resources