Вопрос
Я создал приложение, которое отображает записи из базы данных в окне и проверяет базу данных на наличие новых записей каждые пару секунд. Проблема в том, что окно мигает каждый раз, когда я проверяю наличие новых записей и хочу это исправить. Я попытался сравнить старые данные с новым и обновить только если они разные. Кто-нибудь знает, что является лучшей практикой для таких случаев? Я пытался сделать это следующим образом, но это не работает:
private bool GetBelongingMessages()
{
bool result = false;
DataTable dtTemp = OleDbWorks.GetBelongingMessages(currentCallID);
if(dtTemp != dtMessages)
{
dtMessages = dtTemp;
result = true;
}
else
{
result = false;
}
return result;
}
Решение
Во-первых, важно признать, что то, что вы сравниваете в своем коде, это ссылки таблиц данных, а не содержимое таблиц данных. Чтобы определить, имеют ли обе таблицы данных одинаковое содержимое, вам придется пройтись по всем строкам и столбцам и посмотреть, равны ли они:
//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;
}
Другие советы
Я некоторое время пытался найти способ сравнения DataTable и в итоге написал свою собственную функцию, вот что я получил:
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;
По сравнению с решением Дэйва Маркла, моя обрабатывает две таблицы с одинаковыми записями, но в разных порядках как идентичные. Надеюсь, это поможет тому, кто снова наткнется на эту тему.
Вы должны приводить объекты t1.Rows [i] [dc.ColumnName] и t1.Rows [i] [dc.ColumnName], в противном случае оператор t1.Rows [i] [dc.ColumnName]! = t2.Rows [i] [dc.ColumnName] всегда верно. Я изменил код следующим образом:
for(int i = 0; i < t1.Rows.Count; i++)
{
if((string)t1.Rows[i][1] != (string)t2.Rows[i][1])
return false;
}
и это работает, но это не элегантное решение.
public Boolean CompareDataTables(DataTable table1, DataTable table2)
{
bool flag = true;
DataRow[] row3 = table2.Select();
int i = 0;// row3.Length;
if (table1.Rows.Count == table2.Rows.Count)
{
foreach (DataRow row1 in table1.Rows)
{
if (!row1.ItemArray.SequenceEqual(row3[i].ItemArray))
{
flag = false;
break;
}
i++;
}
}
else
{
flag = false;
}
return flag;
}
// здесь эта функция выдаст логическое значение в качестве результата, возвращающего true, если оба одинаковы, иначе возвращает false, если оба не одинаковы.