Merge Semantics Contract

The Merge Semantics Contract defines predictable, testable merge behavior across UI and non-UI flows and applies to:

Terminology

Public API (Do* merge methods)

The merge API is expressed as four explicit dataset extension methods:

MergeWith exists for backward compatibility only and is marked [Obsolete]. New code should call the explicit Do* methods.

Dataset Level Contract

Table discovery

Exclusions

Table-Level Contract

Tables with primary key

Tables without primary key

Current contract: tables without primary keys use "Replace-like" semantics during refresh operations because safe row-by-row reconciliation is not reliable without keys. This avoids false matches and accidental data corruption.

Merge Methods (Policies)

POCO DataSet and Observable POCO DataSet use the same policies. The only difference is that Observable POCO DataSet raises notification events about changes during the merge process.

1) DoRefreshMergePreservingLocalChanges (non-destructive refresh)

Intent: refresh current content with server truth without overwriting local edits.

Current row state Refreshed row exists Action Result Observable Events
Unchanged Yes Copy refreshed values Unchanged IObservableDataRow.DataFieldValueChanged
Unchanged No Remove row (unless rows excluded from deletion) Row removed IObservableDataTable.RowsRemoved
Modified Yes/No Preserve local edits Modified None
Added Yes/No Preserve local new row Added None
Deleted Yes/No Preserve pending delete Deleted None

Outcome: local edits remain as is; server-applied updates become baseline (Unchanged) for eligible rows.

2) DoRefreshMergeIfNoChangesExist (refresh-only-when-clean)

Intent: enforce that refresh can only happen when the current dataset is a clean baseline. This mode is appropriate for read-only screens, polling, and search result scenarios where local edits are not expected.

Precondition Current state Refreshed snapshot Action Result Observable Events
Must be clean Any row is Added/Modified/Deleted Any Throw and do not merge No changes applied None
Clean baseline All rows are Unchanged Row exists with same PK Copy refreshed values Row stays Unchanged None
Clean baseline All rows are Unchanged Row missing for a current PK Remove row (unless excluded from deletion) Row removed None
Clean baseline All rows are Unchanged New row exists (PK not present in current) Add row Row becomes Unchanged None

3) DoPostSaveMerge (reconciliation after successful save)

Intent: apply server-confirmed values (identity, rowversion, computed fields), finalize deletes, and end in a clean baseline.

Current row state Server row exists Action Result Observable Events
Added Yes Propagate identity/rowversion/computed fields Unchanged IObservableDataRow.DataFieldValueChanged
IObservableDataRow.RowStateChanged
Modified Yes Propagate server-confirmed fields Unchanged IObservableDataRow.DataFieldValueChanged
IObservableDataRow.RowStateChanged
Deleted Yes/No Remove from table (finalize delete) Row removed IObservableDataTable.RowsRemoved
Unchanged Yes Copy refreshed values Unchanged IObservableDataRow.DataFieldValueChanged

Outcome: all remaining rows end as Unchanged.

4) DoReplaceMerge (destructive reload)

Intent: replace the entire local result set (new search results, "load children from scratch", etc.). This mode intentionally does not attempt row-level reconciliation and therefore is not considered a merge in the strict sense.

Current content Refreshed snapshot Action Result Observable Events
Any rows (including pending edits) Any Remove all current rows Table becomes empty IObservableDataTable.RowsRemoved
Empty after clear All refreshed rows Add all refreshed rows All rows are Unchanged IObservableDataTable.RowsAdded

Replace Schema Contract

Replace is easy to accidentally change later. The current policy is:

 

Table of Content POCO DataSet Concepts

 


Business Process Programming in .Net
© 2004–2026 Laskarzhevsky Software Inc.
Unless otherwise noted, the content of this website is licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0).
Code examples are provided under the MIT License.
You are free to share and adapt the material provided that appropriate credit is given and any modifications are clearly indicated.
The information provided on this website is for educational purposes only.
The author and publisher make no warranties regarding the completeness or suitability of the information and are not responsible for any damages resulting from its use.