tags:

views:

587

answers:

5
+1  Q: 

Compare datatables

Hi,

I built an application which displays the records from database in the window and checks the the database for new records every couple of seconds. The problem is that the window blinks each time I check for new records and I want to fix it. I have tried to compare the old datatable with the new one and refresh only if they are different. Does anyone know what is the best practice for such cases? I tried to do it the following way but it doesn't work:

private bool GetBelongingMessages()
        {
            bool result = false;
            DataTable dtTemp = OleDbWorks.GetBelongingMessages(currentCallID);
            if(dtTemp != dtMessages)
            {
                dtMessages = dtTemp;
                result = true;
            }
            else
            {
                result = false;
            }
            return result;
        }
+1  A: 

First off, it's important to regognize that what you're comparing in your code is the references of the datatables, not the contents of the datatables. In order to determine if both datatables have the same contents, you're going to have to loop through all of the rows and columns and see if they're equal:

//This assumes the datatables have the same schema...
     public bool DatatablesAreSame(DataTable t1, DataTable t2) {   
      if (t1.Rows.Count != t2.Rows.Count)
       return false;

      foreach (DataColumn dc in t1.Columns) {
       for (int i = 0; i < t1.Rows.Count; i++) {
        if (t1.Rows[i][dc.ColumnName] != t2.Rows[i][dc.ColumnName]) {
         return false;
        }
       }
      }
      return true;
     }
Dave Markle
A: 

You have to cast objects t1.Rows[i][dc.ColumnName] and t1.Rows[i][dc.ColumnName] otherwise the statement t1.Rows[i][dc.ColumnName] != t2.Rows[i][dc.ColumnName] is always true. I modified the code the following way:

for(int i = 0; i < t1.Rows.Count; i++)
            {
                if((string)t1.Rows[i][1] != (string)t2.Rows[i][1])
                    return false;
            }

and it works but it's not an elegant solution.

niko
It might not work, but it is the solution. I'd mark the above answer as the answer to the question, because there's no better one coming. :)
Omer van Kloeten
A: 

To avoid this blink, try to run your code in a thread running in the background.

mnour
A: 

I already run the code in multiple threads but threads don't solve this problem. Anyway the solution with the datatable comparison posted above works fine!

niko
A: 

I've been trying to find a way to do DataTable comparison for a while and ended up writing up my own function, here is what I got:

bool tablesAreIdentical = true;

// loop through first table
foreach (DataRow row in firstTable.Rows)
{
    foundIdenticalRow = false;

    // loop through tempTable to find an identical row
    foreach (DataRow tempRow in tempTable.Rows)
    {
        allFieldsAreIdentical = true;

        // compare fields, if any fields are different move on to next row in tempTable
        for (int i = 0; i < row.ItemArray.Length && allFieldsAreIdentical; i++)
        {
            if (!row[i].Equals(tempRow[i]))
            {
                allFieldsAreIdentical = false;
            }
        }

        // if an identical row is found, remove this row from tempTable 
        //  (in case of duplicated row exist in firstTable, so tempTable needs
        //   to have the same number of duplicated rows to be considered equivalent)
        // and move on to next row in firstTable
        if (allFieldsAreIdentical)
        {
            tempTable.Rows.Remove(tempRow);
            foundIdenticalRow = true;
            break;
        }
    }
    // if no identical row is found for current row in firstTable, 
    // the two tables are different
    if (!foundIdenticalRow)
    {
        tablesAreIdentical = false;
        break;
    }
}

return tablesAreIdentical;

Compared to Dave Markle's solution, mine treats two table with same records but in different orders as identical. Hope this helps whoever stumbles upon this thread again.

FlyinFish