Domanda

I am trying to remove rows that are not needed from a DataTable. Basically, there may be several rows where the itemID is identical. I want to find the rows where the column "failEmail" = "fail", and using the itemID of those rows, remove all rows from the emails DataTable that have the same itemID.

Here is what I have tried:

System.Diagnostics.Debug.Print(emails.Rows.Count.ToString() + " emails!");

// create a list of the email IDs for records that will be deleted
List<DataRow> rows2Delete = new List<DataRow>();

foreach (DataRow dr in emails.Rows) 
{
   if (dr["failEmail"].ToString().ToLower() == "fail") 
   {
      rows2Delete.Add(dr);
   }
}

foreach (DataRow row in rows2Delete)
{
   DataRow[] drRowsToCheck =emails.Select("itemID ='" + row["itemID"].ToString()  +"'");
   foreach (DataRow drCheck in drRowsToCheck)
   {
      emails.Rows.RemovedDrCheck);
      emails.AcceptChanges();
   }
}

Here is the error message I am getting on the second pass:

This row has been removed from a table and does not have any data. BeginEdit() will allow creation of new data in this row

How can I do what I need to without throwing errors like that? Is there a better way like using a LiNQ query?

È stato utile?

Soluzione 2

this is what I ended up doing, based on an answer I got from MSDN c# Forums:

create an extension on DataTable to enable LINQ euering of the Datatable:

public static class DataTableExtensions
{
   public static IEnumerable<DataRow> RowsAsEnumerable ( this DataTable source )
        {
            return (source != null) ? source.Rows.OfType<DataRow>() : Enumerable.Empty<DataRow>();
        }
}

then modified my code as below:

//Get IDs to delete
var deleteIds = from r in emails.RowsAsEnumerable()
                 where String.Compare(r["failEmail"].ToString(), "fail", true) == 0
                 select r["itemID"];

//Get all rows to delete
var rows2Delete = (from r in emails.RowsAsEnumerable()
                  where deleteIds.Contains(r["itemID"])
                  select r).ToList();

//Now delete them
foreach (var row in rows2Delete)
    emails.Rows.Remove(row);
emails.AcceptChanges();

and now it works, just wish I could do it the normal way successfully.

Altri suggerimenti

The problem is that when the same itemID has multiple entries with 'fail', you are trying to remove them multiple times.

// 1. Find the Unique itemIDs to remove
var idsToRemove = emails.Select("failEmail = 'fail'").Select (x => x["itemID"]).Distinct();
// 2. Find all the rows that match the itemIDs found
var rowsToRemove = emails.Select(string.Format("itemID in ({0})", string.Join(", ", idsToRemove)));
// 3. Remove the found rows.
foreach(var rowToRemove in rowsToRemove)
{
    emails.Rows.Remove(rowToRemove);
}
emails.AcceptChanges();
        foreach (DataRow rowFail in emails.Select("failEmail = 'fail'"))
        {
            DataRow[] rowsItem = emails.Select(String.Format("itemID = '{0}'", rowFail["itemID"]));

            for (int i = rowsItem.Length - 1; i >= 0; i--)
            {
                rowsItem[i].Delete();
            }
        }

        emails.AcceptChanges();

DataTable.Select returns an array of all DataRow objects that match the filter criteria.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top