Filter DataTable Efficiently - c#

What's the most efficient way of filtering DataRows in a DataTable? I have a list of integers and want to retrieve all rows (and eventually create a DataTable from them) which match the integers in the list. I'm currently using the code below, but it's quite slow. Am I missing a more efficient way?
foreach (var i in integerlist)
{
DataRow dr = (from row in originalDataTable.AsEnumerable()
where row.Field<int>("urlID") == i
select row).FirstOrDefault<DataRow>();
if (dr!= null)
{
newDataTable.Rows.Add(dr);
}
}

I suggest you to try to do vice versa.
foreach (var row in originalDataTable)
{
if(integerList.Contains( (int)row["urlID"]))
newDataTable.ImportRow(row)
}
It makes even more sense if you have more rows in dataset then integers in your int collection.
Hope it helps :)

Hm... may be I'm missing something, but...
Woudn't be it easier just use DataView and apply a RowFilter for it ?

you could try doing a join such as:
var resultSet =
from row in originalDataTable.AsEnumerable()
join i in integerlist
on row.Field<int>("urlID") equals i
select row;
that should give you the full result set.
if you need a datatable you could do:
resultSet.CopyToDataTable();

As #Tigran says you can use the dataview, check this msdn article on how to accomplish just that.
Basically you use a DataView to filter the data and the you call the DataView.ToTable method to get the new DataTable.

Related

subtract two DataTables that have the same shema, E.g Minus SQL query

I have two DataTables that have both the same schema (same columns names and types ).I want to get the rows that appear in the first and not in the second one.
Could anyone help me in this? Thanks.
Thankfully, MS has created extension methods for DataTable that let you use Linq methods (like Except) to query data rows, and written a class that implements IEqualityComparer<DataRow> that compares DataRow instances by their column values:
var rows = dt1.AsEnumerable()
.Except(dt2.AsEnumerable(),DataRowComparer.Default);
I would write something like this:
var onlyIn1 = dataTable1.Where( row1 => !dataTable2.Rows.Any( row2 => row1["CustomerKey"] == row2["CustomerKey"]) ).ToList();
You could try this:
var onlyIn1 = db.Table1.Except(db.Table2).ToList();
I never test this, but it should work like T-SQL's EXCEPT

How to Merge rows data From DataTable in C#?

How to Merge rows data From DataTable in C#?
I think that this is a good use case for the LINQ Group clause. You can start with something like this:
var rowGroups = dataTable.Rows.GroupBy(row =>
new {RecptNo = row["recpt_no"], Test = row["Test"]});
foreach(var group in rowGroups)
{
//Here "group" is a collection of rows with the same rectp_no and test. Process as required.
//You could also check group.Key.RecptNo and group.Key.Test here if necessary.
}
Here's a link of that relates to your question. Hope it helps.
How to merge rows in a DataTable when data in multiple columns match?

Use DataGridView.SelectedRows as DataSource for another DataGridView

I want to use the user-selected rows from one DataGridView as the DataSource for a second DataGridView. Note both DataGridViews will have identical columns.
Obviously I can iterate over the selected rows, obtain the key values, and re-query the database for a List to use as the DataSource of the 2nd grid, but that seems lame.
Surely there is an elegant way of simply re-using the SelectedRows collection as a DataSource?
You cannot directly set collection of DataRow as datasource, you can read more details from MSDN
How about doing (bit) traditional way?
var dt = ((DataTable)dataGrid1.DataSource).Clone();
foreach (DataGridViewRow row in dataGrid1.SelectedRows)
{
dt.ImportRow(((DataTable)dataGrid1.DataSource).Rows[row.Index]);
}
dt.AcceptChanges();
dataGrid2.DataSource = dt;
Another way to do this using CopyToDataTable method.
DataTable dtable2;
DataRow[] rowArray = dataGridView1.SelectedRows;
If !(rowArray.Length == 0 )
{
dTable2 = rowArray.CopyToDataTable();
}
dataGrodView2.DataSource = dTable2;
Thanks for your replies. Seems there isn't a very simple way.
I did it this way:
MyDatGridView.SelectedRows.Cast<DataGridViewRow>().Select(dgvr => (int)dgvr.Cells[0].Value).ToList());
Then I tried to use the resulting List with a .Contains in a .Where clause.

How to get unique records of specific columns of data table

I have a DataTable imported from Excel file.
Data i need is only unique from specific columns of the DataTable.
The unique data i meant is like when a command DISTINCT is used in SQL Select Query.
I want to get the list of the unique data from the DataTable Column and put them into List
I think LinQ can be used for this matter but i'm not so familiar with it.
I was thinking of code like this below
var data is from MyDataTable
where MyDataTable.ColumnName = "SpecificColumn"
select MyDataTable["SpecificColumn"]).UniqueData;
List<string> MyUniqueData = new List<string>();
foreach(object obj in data)
{
if(MyUniqueData.NotContain(obj))
MyUniqueData.add(obj);
}
I hope someone can drop off some knowledge to me.
var unique = data.Distinct().ToList();
What you're looking for is .Distinct(). See MSDN documentation here. You can specify your own comparer if you need something specific and it will return only unique records.
If you have a Datatable or DataView, inorder to get unique records from a column, you have to write this.
this would be simple.
DataTable dtNew = dt.DefaultView.ToTable(true, "ColName"); // for Datatable
DataTable dtnew= dv.ToTable(true, "ColName"); // for DataView

How to remove rows from huge data table without iterating it?

I have a DataTable available with me which contains thousands of rows. There is a column called EmpID which is containing '0' for some of the rows. I want to remove them from my current DataTable and want to create a new correct DataTable. I cannot go row by row checking it since it contains huge amount of data. Give me a suggestion to overcome this problem.
the best way would be to filter it at source (if possible) - so if you are creating it from a db, exclude all 0 values in your sql query itself using a where
starting .net 2.0, ms enhanced the filtering logic on the datatable to a great extent. so if you used the dataview (on top of your datatable) and added the where clause in there and added some sort of runtime indexes on this field, it would give you the desired results without looping over all records
You can use DataTable.Select("EmpID <> 0"). This will return an array of DataRows which you can create your new DataTable from if required.
Isn't it possible to first select the rows with EmpID = 0 and then iterate over these only ?
DataTable newTable = new DataTable();
foreach (DataRow dr in oldTable.Select("EmpID = '0'")) {
newTable.Rows.Add(dr);
oldTable.Rows.Remove(dr);
}
You can try
DataRow[] temp=
table.Select("EmpID ='0'");
foreach(DataRow dr in temp)
{
table.Rows.Remove(dr);
}
table.acceptchanges();

Categories