2010-07-22 9 views
0

Je souhaite effectuer une opération Except sur un ensemble d'éléments.LINQ sélectionne les éléments de l'ensemble A qui ne sont pas dans l'ensemble B

code

est comme ceci:

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

Maintenant, comment sélectionner les colonnes de DataSet.Tables [0] qui ne sont pas en dgvColumns? Je sais que les colonnes de DataGridView sont de type différent de Columns dans DataSet. Je veux ramasser seulement un sous-ensemble de valeurs communes. Comme ceci:

 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 }; 

Le code ci-dessus me sélectionne "colonnes" qui sont dans les deux ensembles. Alors J'pensais je vais créer une autre série de « colonnes » qui sont DataSet:

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

et maintenant que je serai en mesure de perfrom Sauf comme ceci:

var ColumnsOnlyInDS = ColumnsInDS.Except<ColumnsInDGV>; 

Mais je reçois deux erreurs :

  1. Le type ou le nom namespace « ColumnsInDGV » n'a pas pu être trouvé (vous manque une directive à l'aide ou une référence d'assemblage?)
  2. ne peut pas affecter la méthode g roup à une variable locale implicitement typée

Donc la solution serait de construire une classe et de l'utiliser à la place de la variable locale implicitement typée. Mais je pense que le développement d'une classe uniquement pour cette raison n'est pas une dépense inutile.

Existe-t-il une autre solution à ce problème?

Répondre

3

Vous l'avez presque compris. Vous avez juste besoin d'écrire:

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

au lieu de:

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

Mise à jour: Donc, en fait ce qui précède ne fonctionne pas parce que Except dépend de la comparaison des éléments de deux séquences pour l'égalité; Évidemment, votre type anonyme n'a pas dépassé object.Equals et ainsi chaque objet que vous créez de ce type est traité comme une valeur distincte. Essayez ceci à la place *:

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); 

* Note: Where dans l'expression ci-dessus pour dsDgvColumns plus de sens que SkipWhile parce qu'il appliquera le filtre spécifié sur tous résultats. SkipWhile n'appliquerait le filtre que s'il était vrai et cesserait alors de l'appliquer. En d'autres termes, cela fonctionnerait si votre DataGridViewColumn non lié à votre DataSet était au commençant du DataGridView; mais pas si c'était au milieu ou à la fin.

+0

Merci! La première solution n'a pas fonctionné, aucune erreur de compilation mais a retourné toutes les colonnes. La deuxième solution a fonctionné, après avoir effectué 'var dsDgvColumns = dgvColumns.Select (c => dsColumns [c.DataPropertyName])'; il y a une colonne null dans dsDgvColumns. Peut-être que la raison en est que j'ai une colonne dans DataGridView qui n'est pas dans DataSet.Comment modifier la requête ci-dessus d'une manière que dsDgvColumns ne containt pas les valeurs nulles? – Wodzu

+0

Je l'ai modifié comme ceci pour se débarrasser des nulls. Je ne sais pas si c'est la méthode optimale pour le faire? var dsDgvColumns = dgvColumns.SkipWhile (c => dsColumns [c.DataPropertyName] == null) .Sélectionnez (c => dsColumns [c.DataPropertyName]); – Wodzu

+0

@Wodzu: 'Where' serait plus approprié que' SkipWhile'. Aussi, il m'est venu à l'esprit pourquoi la première solution n'a pas fonctionné. Voir ma modification. –