表没有主键c#

时间:2013-05-15 07:05:59

标签: c# datatable

我尝试使用DataTable AllItems中的行从DataTables Items删除行;这样做的目的是从DataTable AllItems中获取不在DataTable Items

内的项目

所有这些行都来自同一Excel文件,该文件包含多个列并且相等。

我尝试过使用foreach循环:

foreach(DataRow dr in AllItems.Rows)
{
if (Items.Contains(dr))
{
AllItems.Rows.Remove(dr);
}

但我收到以下错误:表没有主键。

有谁知道我怎么能删除这些行?

2 个答案:

答案 0 :(得分:1)

你有几个选择:

<强> 1。添加主键

您可以在创建时添加primary key to your data table

假设您有一个名为“Id”的列,那么您可以这样做:

AllItems.PrimaryKey = new DataColumn[] { workTable.Columns["Id"] };} 

或者,对于主键是复合键(多列)的情况:

AllItems.PrimaryKey = new DataColumn[] { 
                             workTable.Columns["Id"], 
                             workTable.Columns["Name"] };} 

这样就可以让Contains正常工作。

<强> 2。使用DataView

您可以使用DataView过滤掉不同的行;

DataView view = new DataView(AllItems);
DataTable distinctValues = view.ToTable(true, "Column1", "Column2" , ..., "ColumnN");

第3。使用选择

查找匹配行

或者您可以依赖Select方法来测试Items DataTable中是否存在基于类似SQL WHEREclause的语句的相应行:

List<DataRow> rowsToRemove = new List<DataRow>();

foreach(DataRow allItemRow in AllItems.Rows)
{
    if(Items.Select(String.Format("Id = {0}"), 
          allItemRow.Field<Int32>("Id")).Length == 0)
    {
        rowsToRemove.Add(allItemRow);
    }
}

rowsToRemove.ForEach(x => x.Delete());

AllItems.AcceptChanges();

注意重要的是,在迭代AllItems中的行集合时不要删除行 - 而是收集这些行,然后删除它们。

<强> 4。在

中的路上过滤

另请注意,我还没有尝试过,但是,根据您从Excel中选择行的方式,您可以使用SQL DISTINCT子句;如果您使用ODBC to load data from Excel,那么您可以尝试在源代码进行过滤。

答案 1 :(得分:0)

你可以试试这个:

var exceptItems = AllItems.Rows.Cast<DataRow>()
    .Except(Items.Rows.Cast<DataRow>(), DataRowComparer.Default)
    .ToList();

作为替代方案,如果您希望在从中移除allItems行后继续使用items数据表,则可以尝试此操作(假设您拥有列Id在两个数据表中,每个数据表唯一标识一行):

var exceptItems = AllItems.Rows.Cast<DataRow>()
    .Select((i, index) => new { id = i["Id"], index })
    .Intersect(Items.Rows.Cast<DataRow>()
        .Select((i, index) => new { id = i["Id"], index }))
    .ToList();

for (int i = exceptItems.Count()-1; i >= 0; i--)
{
    AllItems.Rows.RemoveAt(exceptItems[i].index);
}

以上是上一个例子的更好的安排:

AllItems.Rows.Cast<DataRow>()
    .Select((i, index) => new { id = i["Id"], index })
    .Intersect(Items.Rows.Cast<DataRow>()
        .Select((i, index) => new { id = i["Id"], index }))
    .OrderByDescending(i => i.index)
    .ToList()
    .ForEach(i => AllItems.Rows.RemoveAt(i.index));