2010-07-22 88 views
0

我想对集合项目执行Except操作。LINQ从集合A中选择不在集合B中的项目

代码是这样的:

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. 无法分配方法G群到隐式类型的局部变量

所以解决方案是建立一个类,然后用它来代替隐式类型化的局部变量。但我认为仅仅因为这个原因才开发一个类是一个不必要的开销。

这个问题还有其他解决方案吗?

回答

3

你已经差不多了。你只需要编写:的

// 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,因此您创建的此类型的每个对象都被视为不同的值。在上述表达式WheredsDgvColumns更有意义比SkipWhile,因为它将应用指定的过滤器超过所有结果:试试这个*代替:

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

*注。 SkipWhile将只应用过滤器,只要它是真实的,然后将停止应用它。换句话说,如果您的DataGridViewColumn未绑定到您的DataSet位于DataGridView开始;但如果它在中间或结束则不会。

+0

谢谢!第一个解决方案不起作用,没有编译器错误,但已返回所有列。第二种解决方案在执行'var dsDgvColumns = dgvColumns.Select(c => dsColumns [c.DataPropertyName])'后运行, dsDgvColumns中有一个空列。也许原因是我在DataGridView中有一列不在DataSet中。如何以dsDgvColumns不包含空值的方式修改上述查询? – Wodzu 2010-07-23 09:51:29

+0

我已经像这样修改它来摆脱空值。我不知道这是否是最佳方法来做到这一点? var dsDgvColumns = dgvColumns.SkipWhile(c => dsColumns [c.DataPropertyName] == null) .Select(c => dsColumns [c.DataPropertyName]); – Wodzu 2010-07-23 10:18:14

+0

@Wodzu:'哪里比'SkipWhile'更合适。另外,我想到了为什么第一个解决方案不起作用。看我的编辑。 – 2010-07-23 11:43:19