Демо IV. Определение и устранение конфликтов   

   

Демо IV. Определение и устранение конфликтов

 Наш способ разрешения конфликтов будет касаться времени. Конфликты возникают в окружениях ленивой синхронизации. Скорее всего, пользователи ваших приложений не захотят иметь дело с конфликтами. Поэтому вам следует построить ваше приложение таким образом, чтобы конфликты возникали как можно реже. Однако, ваше приложение будет неполным без механизмов разрешения конфликтов. Прежде чем пойти дальше, я дам определение конфликту:

 «Будем считать, что строка находится в конфликте, если она изменена в двух или более узлах между запросами синхронизации».

 В среде с двумя узлами клиент сможет внести изменения в строку R, находясь в оффлайне, в то же время на сервере могут тоже внести изменения в R. При синхронизации обоих изменений возникает конфликт. В n-узловой среде конфликт может возникнуть из-за независимых изменений, вносимых в R двумя или более клиентами.


Типы конфликтов

 Система синхронизации определяет четыре типа конфликтов:

  • ClientInsertServerInsert также известен как PK-конфликт; возникает, когда клиент и сервер вставляют строку с одним и тем же PK
  • ClientUpdateServerUpdate – наиболее распространенный конфликт, возникающий когда сервер и клиент одновременно изменяют одну и ту же строку
  • ClientUpdateServerDelete возникает, когда клиент обновляет некоторую строку, а сервер ее удаляет
  • ClientDeleteServerUpdate возникает, когда клиент удаляет некоторую строку, а сервер ее обновляет

Примечание: Использование термина «сервер» в описанных выше типах конфликтов не обязательно означает, что изменения были произведены на сервере. На самом деле сервер может быть всего лишь пассивным узлом, который только собирает и распределяет изменения. Однако, с точки зрения синхронизации клиента, все изменения происходят на сервере.

Чтобы создать каждый из приведенных типов конфликтов, я добавил четыре кнопки в основную форму, как показано на рисунке:

Обнаружение и разрешение конфликтов:


Система синхронизации инициирует ApplyChangeFailedEvent со стороны клиента и сервера, в случае обнаружения конфликта. В этом демонстрационном приложении я зарегистрировал получение событий конфликтов как с сервера так и от клиента. Каждый конфликт представлен пользователю со всеми возможностями его разрешения:

  1. Игнорировать конфликт и продолжать
  2. Попробовать еще раз применить изменения. Без изменений данных это приведет к повторному возникновению конфликта. Однако, наша программа не позволяет вам редактировать данные.
  3. Попробовать еще раз с форсированием записи встроена в ClientSyncProvider на серверной стороне. Вам остается реализовать ее на клиенте, как в нашей программе, где реализован пример разрешения конфликта типа обновление-обновление.
  4. Прекратить синхронизацию вызвав исключение. Все изменения будут стерты и пересинхронизированы в следующем сеансе.

create procedure dbo.sp_orders_applyupdate (   
    @sync_last_received_anchor binary(8) ,
    @sync_client_id_hash int ,
    @sync_force_write int,
    @sync_rowcount int out,
    @order_id int,
    @order_date datetime = NULL )       
as         
    update [orders]
        set [order_date] = @order_date,
            [update_originator_id] = @sync_client_id_hash
        where (update_timestamp <= @sync_last_received_anchor or update_originator_id = 
               @sync_client_id_hash) and [order_id] = @order_id
    set @sync_rowcount = @@rowcount     

    -- force write resolution option
    if @sync_rowcount = 0 and @sync_force_write = 1
    begin
        update [orders]
        set [order_date] = @order_date,
            [update_originator_id] = @sync_client_id_hash    
        set @sync_rowcount = @@rowcount
    end  
go

Команды конфликтов SyncAdapter

Существует две команды, с которыми мы не столкнулись в предыдущих демонстрациях:

  • SelectConflictUpdatedRowsCommand эта команда находит конфликтующие строки в основной таблице. Во время выполнения программы эта команда запускается в случае неудачного выполнения вставки, обновления или удаления (т.е. возвращения ими 0 количества строк)
  • SelectConflictDeletedRowsCommand эта команда находит конфликтующие строки в таблице индексов. Во время выполнения программы эта команда запускается в случае, если конфликтующие строки не найдены в основной таблице. Таким образом определяется конфликт ClientUpdateServerDelete.

Написать эти команды можно очень просто, как показано ниже:

create procedure dbo.sp_orders_getupdateconflict
    @order_id int
as
    -- this command finds the conflicting row in the base table for [orders]
    select order_id, order_date from orders where order_id = @order_id
go

create procedure dbo.sp_orders_getdeleteconflict
    @order_id int
as
   
    -- this command finds the conflicting row in the tombstone table for [orders]
    select order_id from orders_tombstone where order_id = @order_id
go

Шаги инсталляции приложения OfflineAppDemo:

  1. Запустите SQL Server и загрузите файл demo.sql
  2. Запустите скрипт до маркера "test sample"
  3. Загрузите файл server_procs.sql и запустите его для создания процедур синхронизации на сервере
  4. Загрузите решение VS (OfflineAppDemo-Builder Project)
  5. Скомпилируйте проект
  6. Все готово