Создание DataTable путем фильтрации другого DataTable - PullRequest
4 голосов
/ 23 декабря 2010

Я работаю в системе, которая в настоящее время имеет довольно сложную функцию, которая возвращает DataTable, который затем привязывается к элементу управления GUI в ASP.NET WebForm.

Моя проблема заключается в том, что мне нужнофильтруйте возвращаемые данные - некоторые возвращаемые данные не должны отображаться пользователю.

Мне известно о DataTable.select (), но это не совсем то, что мне нужно.Во-первых, он возвращает массив DataRows, и мне нужен DataTable, чтобы я мог привязать его к элементу управления GUI.Но что еще более важно, фильтрация, которую я должен сделать, - это не то, что можно легко выразить простым выражением.У меня есть массив элементов, которые я не хочу отображать, и мне нужно сравнить каждый элемент из DataTable с этим массивом.

Что я мог бы сделать, конечно, это создать новый DataTable, читаявсе из оригинала, добавляя к новому то, что подходит, затем привязывая данные к новому элементу управления GUI.Но это как-то не так.В этом случае число элементов в исходной таблице DataTable вряд ли будет достаточным, чтобы копирование их всех в памяти могло вызвать слишком много проблем, но мне интересно, есть ли другой способ.

Имеет ли .NET DataTable функциональность, позволяющую фильтровать через функцию обратного вызова?

Ответы [ 3 ]

17 голосов
/ 24 декабря 2010

Используйте метод DataView.ToTable:

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

Если вы не можете поместить свою логику фильтрации в выражение фильтра, вы можете прибегнуть к 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();

Или, если у вас уже есть метод, который реализует фильтрацию:

bool FilterRow(DataRow row)
{
    ...
}

...

var newTable = sourceTable.AsEnumerable().Where(FilterRow).AsDataView().ToTable();
2 голосов
/ 24 декабря 2010

Как насчет привязки элемента управления GUI к списку строк данных, который удовлетворяет вашему условию? как то так:

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

Делая это таким образом, datarows не будут скопированы, но список будет содержать ссылки на нужные вам строки.

1 голос
/ 23 декабря 2010

Я не знаю, что вы имеете в виду с функцией обратного вызова .

Возможно, другие порекомендуют для этого 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

Вы также можете использовать Dataview в качестве источника вашего второго элемента управления, используя свойство RowFilter :

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

Вы также можете использовать синтаксис IN и NOT IN для фильтрации по списку / массиву элементов для Select и RowFilter, например:

dv.RowFilter = "SomeID NOT IN(1,2,3)"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...