How to append row in DataTable? - c#

I'm trying to append more values the rows of a DataTable. The original data read from database doesn't have two additional columns I'd like to add. I've got this so far -
myTable.Columns.Add("type", typeof(int));
myTable.Columns.Add("rate", typeof(int));
foreach (DataRow rows in myTable.Rows)
{
if (rows["dst"] == "1875")
{
//How to append values to this current row?
}
}
Please advice.

Here is the answer
foreach (DataRow rows in myTable.Rows)
{
if (rows["dst"] == "1875")
{
//How to append values to this current row?
rows["type"] = 32;
rows["rate"] = 64;
}
}
Also as a best practice - change rows in your for loop to row. It should be singular as it represents a single object - not a collection.

Related

How to copy values from a datatable column into a datagridview column in windows forms in c# without iterating every single row?

I have more than 9000 rows and 18 columns in my datagridview. I have to read the columns from an external datatable. If I find a match between column names, I have to copy all values from the datatable column into the datagridview column. My problem is, I cannot iterate over these rows for 18 times for more than 9000 rows and write for every iteration the value in the datagridview cell because it is too slow. Is there any valid alternative?
I add some code below so that you can understand better my question. Here I'm iterating the columns first, then the rows. Sorry for the indentation but I'm having problems in copy paste code on StackOverflow.
dgvMappatura is my dataGridView, dtExcel is my DataTable
foreach (DataColumn col in dtExcel.Columns)
{
if (col.ColumnName.Equals(nome_colonna_origine))
{
foreach (DataRow drExcel in dtExcel.Rows)
{
// some code to add values to datagridview from the datatable column
}
}
}
See if following is faster :
DataTable dt = new DataTable();
foreach (DataRow row in dt.AsEnumerable())
{
var matches = row.ItemArray.Select((x, i) => new { name = x.ToString(), index = i }).GroupBy(x => x.name).Where(x => x.Count() > 1).ToArray();
}

Get specific column from DataRow without iteration through every column

Im new to DataSets and I am trying to get a specific column from a DataSet. I wrote this code
using (var dataset = new U2ZFDataSetTableAdapters.stationenTableAdapter())
{
var ds = new U2ZFDataSet();
dataset.Fill(ds.stationen);
var rows = ds.stationen.Select("pdvorhanden = 1");
foreach (DataRow row in rows)
{
foreach (DataColumn column in ds.stationen.Columns)
{
if(column.ColumnName == "Bezeichnung")
listOfStations.Add(row[column].ToString());
}
}
}
The code feels slow to me. Isnt there a better way to do this? How can I get a specific Colum from DataRow without iterating through every column of the row?
Access to the column via column name.
foreach (DataRow row in rows)
{
listOfStations.Add(row["Bezeichnung"].ToString());
}
https://msdn.microsoft.com/en-us/library/146h6tk5(v=vs.110).aspx

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.

Delete Duplicate records from large csv file C# .Net

I have created a solution which read a large csv file currently 20-30 mb in size, I have tried to delete the duplicate rows based on certain column values that the user chooses at run time using the usual technique of finding duplicate rows but its so slow that it seems the program is not working at all.
What other technique can be applied to remove duplicate records from a csv file
Here's the code, definitely I am doing something wrong
DataTable dtCSV = ReadCsv(file, columns);
//columns is a list of string List column
DataTable dt=RemoveDuplicateRecords(dtCSV, columns);
private DataTable RemoveDuplicateRecords(DataTable dtCSV, List<string> columns)
{
DataView dv = dtCSV.DefaultView;
string RowFilter=string.Empty;
if(dt==null)
dt = dv.ToTable().Clone();
DataRow row = dtCSV.Rows[0];
foreach (DataRow row in dtCSV.Rows)
{
try
{
RowFilter = string.Empty;
foreach (string column in columns)
{
string col = column;
RowFilter += "[" + col + "]" + "='" + row[col].ToString().Replace("'","''") + "' and ";
}
RowFilter = RowFilter.Substring(0, RowFilter.Length - 4);
dv.RowFilter = RowFilter;
DataRow dr = dt.NewRow();
bool result = RowExists(dt, RowFilter);
if (!result)
{
dr.ItemArray = dv.ToTable().Rows[0].ItemArray;
dt.Rows.Add(dr);
}
}
catch (Exception ex)
{
}
}
return dt;
}
One way to do this would be to go through the table, building a HashSet<string> that contains the combined column values you're interested in. If you try to add a string that's already there, then you have a duplicate row. Something like:
HashSet<string> ScannedRecords = new HashSet<string>();
foreach (var row in dtCSV.Rows)
{
// Build a string that contains the combined column values
StringBuilder sb = new StringBuilder();
foreach (string col in columns)
{
sb.AppendFormat("[{0}={1}]", col, row[col].ToString());
}
// Try to add the string to the HashSet.
// If Add returns false, then there is a prior record with the same values
if (!ScannedRecords.Add(sb.ToString())
{
// This record is a duplicate.
}
}
That should be very fast.
If you've implemented your sorting routine as a couple of nested for or foreach loops, you could optimise it by sorting the data by the columns you wish to de-duplicate against, and simply compare each row to the last row you looked at.
Posting some code is a sure-fire way to get better answers though, without an idea of how you've implemented it anything you get will just be conjecture.
Have you tried Wrapping the rows in a class and using Linq?
Linq will give you options to get distinct values etc.
You're currently creating a string-defined filter condition for each and every row and then running that against the entire table - that is going to be slow.
Much better to take a Linq2Objects approach where you read each row in turn into an instance of a class and then use the Linq Distinct operator to select only unique objects (non-uniques will be thrown away).
The code would look something like:
from row in inputCSV.rows
select row.Distinct()
If you don't know the fields you're CSV file is going to have then you may have to modify this slightly - possibly using an object which reads the CSV cells into a List or Dictionary for each row.
For reading objects from file using Linq, this article by someone-or-other might help - http://www.developerfusion.com/article/84468/linq-to-log-files/
Based on the new code you've included in your question, I'll provide this second answer - I still prefer the first answer, but if you have to use DataTable and DataRows, then this second answer might help:
class DataRowEqualityComparer : IEqualityComparer<DataRow>
{
public bool Equals(DataRow x, DataRow y)
{
// perform cell-by-cell comparison here
return result;
}
public int GetHashCode(DataRow obj)
{
return base.GetHashCode();
}
}
// ...
var comparer = new DataRowEqualityComparer();
var filteredRows = from row in dtCSV.Rows
select row.Distinct(comparer);

Remove row from generic datatable in C#

I ran into a problem trying to remove a row from a datatable in C#. The problem is that the datatable is built from SQL, so it can have any number of columns and may or may not have a primary key. So, I can't remove a row based on a value in a certain column or on a primary key.
Here's the basic outline of what I'm doing:
//Set up a new datatable that is an exact copy of the datatable from the SQL table.
newData = data.Copy();
//...(do other things)
foreach (DataRow dr in data.Rows)
{
//...(do other things)
// Check if the row is already in a data copy log. If so, we don't want it in the new datatable.
if (_DataCopyLogMaintenance.ContainedInDataCopyLog(dr))
{
newData.Rows.Remove(dr);
}
}
But, that gives me an error message, "The given DataRow is not in the current DataRowCollection". Which doesn't make any sense, given that newData is a direct copy of data. Does anyone else have any suggestions? The MSDN site wasn't much help.
Thanks!
Your foreach needs to be on the copy, not the original set. You cannot remove an object contained in collection1 from collection2.
foreach (DataRow dr in newData.Rows)
Otherwise you could use a counter to remove at an index. Something like this:
for(int i = 0; i < data.Rows.Count; i++)
{
if (_DataCopyLogMaintenance.ContainedInDataCopyLog(data.Rows[i]))
{
newData.Rows.RemoveAt(i);
}
}

Categories