GetChanges возвращает копию датасета с изменениями.
При сохранении этой копии адаптер обновляет значение первичного ключа.
т.е.
было id = 1
стало id = N (следующее значение для данной таблицы в бд).
Слияние производится по значению первичного ключа.
Т.к. в исходном датасете строка имеет id = 1, а в датасете с изменениями id = N, то Merge добавит в исходный датасет еще одну строку с id = N.
Чтобы все получилось нужно удалить из исходного датасета все добавленные строки, а только потом делать Merge.