Creating a DataTable by filtering another DataTable

I am working on a system that currently has a rather sophisticated function that returns a DataTable, which then binds to a GUI control in ASP.NET WebForm.

My problem is that I need to filter the returned data - some data that is returned should not be displayed to the user.

I know about DataTable.select (), but this is not quite what I need. First, it returns an array of DataRows, and I need a DataTable, so I can bind it to a GUI control. But more importantly, the filtering I need to do is not something that can easily be expressed with a simple expression. I have an array of elements that I do not want to display, and I need to compare each element from the DataTable with this array.

What I can do, of course, is to create a new DataTable, read everything from the original, add a new one that fits, and then bind a new one to the GUI control. But it somehow seems wrong. In this case, the number of elements in the original DataTable is unlikely to be enough to copy them all into memory, which will cause too many problems, but I wonder if there is another way.

Does the .NET DataTable have functionality that would allow me to filter through a callback function?

+3
source share
3 answers

How to associate GUI control with a DataRows list that satisfies your condition? something like that:

var lst = new List<DataRow>();
foreach(DataRow dr in dt.Rows) {
  if (SatisfiesCondition(dr)) lst.Add(dr);
}

// in Linq dialect
var lst = dt.AsEnumerable().Where(SatisfiesCondition).ToList();

// here: bind control to list

By doing this this way, datarows will not be copied, but the list will retain links to the lines you need.

+2
source

Use the method DataView.ToTable:

DataTable sourceTable = ...
string filter = ...
string sort = ...
DataView view = new DataView(sourceTable, filter, sort, DataViewRowState.CurrentRows);
DataTable newTable = view.ToTable();

If you cannot put your filtering logic in a filter expression, you can resort to Linq to DataSet :

var query = from row in sourceTable.AsEnumerable()
            where row.Field<int>("foo") > 42
            && row.Field<string>("bar") == "hello"
            && ...
            select r;

var newTable = query.AsDataView().ToTable();

Or, if you already have a method that implements filtering:

bool FilterRow(DataRow row)
{
    ...
}

...

var newTable = sourceTable.AsEnumerable().Where(FilterRow).AsDataView().ToTable();
+15
source

, .

, LINQ. 3.5 Framework, .

Datatable? Datatable.Select:

Private Function SelectIntoDataTable(ByVal selectFilter As String, ByVal sourceDataTable As DataTable) As DataTable
    Dim newDataTable As DataTable = sourceDataTable.Clone
    Dim dataRows As DataRow() = sourceDataTable.Select(selectFilter)
    Dim typeDataRow As DataRow

    For Each typeDataRow In dataRows
        newDataTable.ImportRow(typeDataRow)
    Next
    Return newDataTable
End Function

You can also use Dataview as the source of your second control using the RowFilter property :

DataView dv = new DataView( sourceDataTable );
dv.RowFilter = selectFilter 
GridView1.DataSource = dv

You can also use the syntax INand NOT INto filter the list / array elements for the Select and RowFilter, for example:

dv.RowFilter = "SomeID NOT IN(1,2,3)"
+1
source

Source: https://habr.com/ru/post/1781898/


All Articles