Такое поведение вставки по сравнению с обновлением обычно происходит из-за отсутствия определенных первичных ключей. Вы установили первичные ключи на столах? Вот как столбцы сопоставляются во время слияния. За MSDN (выделено мое):
При объединении нового исходного набора данных в
цель, любые исходные строки с
Значение DataRowState без изменений,
Изменены или удалены , соответствующие
целевые строки с одинаковым первичным ключом
Значения . Исходные строки с
Значение DataRowState добавлено
соответствует новым целевым строкам с
те же значения первичного ключа как новый
исходные строки.
Поэтому для каждого DataTable
следует установить свойство PrimaryKey
. Я написал подробный пример этого на странице MSDN DataTable.Merge
несколько лет назад. Вы можете посмотреть на эту запись здесь: Слияние с использованием первичных ключей для ожидаемых результатов .
Краткий пример такого подхода:
DataTable dt1 = new DataTable();
dt1.Columns.Add("ID", typeof(int));
dt1.Columns.Add("Customer", typeof(string));
dt1.PrimaryKey = new[] { dt1.Columns["ID"] };
dt1.Rows.Add(new object[] { 1, "Ahmad" });
DataTable dt2 = new DataTable();
dt2.Columns.Add("ID", typeof(int));
dt2.Columns.Add("Customer", typeof(string));
dt2.PrimaryKey = new[] { dt2.Columns["ID"] };
dt2.Rows.Add(new object[] { 1, "Mageed" });
// try without primary keys and it'll add a new record
dt1.Merge(dt2);
РЕДАКТИРОВАТЬ: относительно вашего комментария, вы можете отклонить изменения в объединенных строках, которые на самом деле не были изменены, пройдя таблицу с помощью кода ниже. Метод, который принимает DataTable
, будет более аккуратным. Важно, чтобы этот код использовался до вызова метода DataTable.AcceptChanges()
, в противном случае состояния строк будут отброшены.
С LINQ:
foreach (DataRow row in dt1.Rows)
{
if (row.RowState == DataRowState.Modified)
{
var original = dt1.Columns.Cast<DataColumn>()
.Select(c => row[c, DataRowVersion.Original]);
bool isUnchanged = row.ItemArray.SequenceEqual(original);
if (isUnchanged)
{
row.RejectChanges();
}
}
}
Если LINQ не поддерживается:
foreach (DataRow row in dt1.Rows)
{
if (row.RowState == DataRowState.Modified)
{
bool isUnchanged = true;
foreach (DataColumn col in dt1.Columns)
{
if (!row[col.ColumnName].Equals(row[col.ColumnName, DataRowVersion.Original]))
{
isUnchanged = false;
break;
}
}
if (isUnchanged)
{
row.RejectChanges();
}
}
}
Вы можете позвонить dt1.AcceptChanges()
после того, как это будет сделано.