LINQ выберите элементы из набора A, которых нет в наборе B - PullRequest
0 голосов
/ 22 июля 2010

Я хотел бы выполнить операцию «Исключить» для набора элементов.

Код такой:

IEnumerable<DataGridViewColumn> dgvColumns = dataGridView.Columns.OfType<DataGridViewColumn>();
IEnumerable<DataColumn> dsColumns = dataSet.Tables[0].Columns.OfType<DataColumn>();

Теперь, как выбрать столбцы из dataSet.Tables [0], которых нет в dgvColumns? Я знаю, что столбцы из DataGridView другого типа, чем столбцы в DataSet. Я хочу подобрать только подмножество общих ценностей. Как это:

        var ColumnsInDGV = from c1 in dgvColumns
                           join c2 in dsColumns on c1.DataPropertyName equals c2.ColumnName
                           select new { c1.HeaderText, c1.DataPropertyName, c2.DataType, c1.Visible };

Над кодом выбираются те «столбцы», которые есть в обоих наборах. Поэтому я решил создать еще один набор «столбцов» в DataSet:

  var ColumnsInDS = from c2 in dsColumns select new { HeaderText = c2.ColumnName, DataPropertyName = c2.ColumnName, c2.DataType, Visible = false };

и теперь, когда я смогу выполнить, кроме как вот так:

var ColumnsOnlyInDS = ColumnsInDS.Except<ColumnsInDGV>;

Но я получаю две ошибки:

  1. Не удалось найти тип или имя пространства имен 'ColumnsInDGV' (отсутствует директива using или ссылка на сборку?)
  2. Невозможно назначить группу методов для неявно типизированной локальной переменной

Таким образом, решением было бы создать класс и затем использовать его вместо неявно типизированной локальной переменной. Но я думаю, что разработка класса только по этой причине не обязательна.

Есть ли другое решение этой проблемы?

1 Ответ

3 голосов
/ 22 июля 2010

Вы почти получили это. Вам просто нужно написать:

// use () to pass a parameter
// type (should) be inferred
var ColumnsOnlyInDS = ColumnsInDS.Except(ColumnsInDGV);

вместо:

// do not use <> - that passes a type parameter;
// ColumnsInDGV is not a type
var ColumnsOnlyInDS = ColumnsInDS.Except<ColumnsInDGV>;

Обновление : Таким образом, вышеприведенное фактически не работает, потому что Except зависит от сравнения элементов в двух последовательностях на равенство; очевидно, ваш анонимный тип не переопределяет object.Equals, поэтому каждый создаваемый вами объект этого типа обрабатывается как отдельное значение. Попробуйте это * вместо этого:

var dgvColumns = dataGridView.Columns.Cast<DataGridViewColumn>();
var dsColumns = dataSet.Tables[0].Columns;

// This will give you an IEnumerable<DataColumn>
var dsDgvColumns = dgvColumns
    .Where(c => dsColumns.Contains(c.DataPropertyName))
    .Select(c => dsColumns[c.DataPropertyName]);

// Then you can do this
var columnsOnlyInDs = dsColumns.Cast<DataColumn>().Except(dsDgvColumn);

* Примечание: Where в вышеприведенном выражении для dsDgvColumns имеет больше смысла, чем SkipWhile, поскольку он будет применять указанный фильтр к всем результатам. SkipWhile будет применять фильтр только до тех пор, пока он будет истинным, а затем прекратит его применение. Другими словами, это сработало бы, если бы ваши DataGridViewColumn не привязывались к DataSet в начале из DataGridView; но не в середине или в конце.

...