identity_insert и проблема синхронизации - PullRequest
0 голосов
/ 18 января 2011

Я использую SQL Server 2008, visual studio 2008, linq, ado.net в моем текущем проекте. Этот проект реализован в Интернете и на рабочем столе.

Теперь моя проблема с синхронизацией данных между веб-базой данных и настольной базой данных.

здесь синхронизация выглядит следующим образом:

  1. новые данные, вставленные в клиент, синхронизируются с сервером.
  2. Обновленные данные в клиенте синхронизируются с сервером.

здесь позвольте мне показать вам мою структуру таблицы.

допустим, мое имя таблицы "customer" с полями

клиент
...................
customerno, bigint, первичный ключ, не ноль, идентификатор true (начиная с 1)
имя, ...
фамилия, ...

теперь у меня будет та же самая таблица в клиенте, но идентификация первичного ключа начнется с 20000. Эта идентификация первичного ключа зависит от количества клиентских систем. рассмотрим следующий сценарий

сервер = customerno, начиная с 1, с 1 записью в таблице
client1 = customerno, начиная с 20000, с 2 записями в таблице
client2 = customerno, начиная с 30000, с 3 записями в таблице

теперь, когда я нажимаю синхронизацию в client1, используя следующий код

        cmd.CommandText = "set identity_insert " + tableName + " on";
        cmd.ExecuteNonQuery();

        foreach (string query in this.queries)
        {
            cmd.CommandText = query; // this is my insert query
            cmd.ExecuteNonQuery();
        }

        cmd.CommandText = "set identity_insert " + tableName + " off";
        cmd.ExecuteNonQuery();

, поскольку linq не поддерживает identity_insert, я использую ado.net

в моем коде сначала я включаю identity_insert, вставляю данные и, наконец, отключаю identity_insert.

теперь вот моя проблема, после синхронизации данных с client1, и две записи вставляются на сервер с customerno как 20001,20002.

согласно http://msdn.microsoft.com/en-us/library/ms188059.aspx

для идентификатора столбца customerno на сервере установлено максимальное значение (в этом случае это будет 20002).

так что теперь, когда я вставляю данные на сервер, он вставляется с customerno как 20003.

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

учитывая вышеописанный случай, перед синхронизацией у нас есть 1 запись на сервере, и ее идентификатор равен 1, поэтому после синхронизации (с одним или несколькими клиентами) я хочу, чтобы следующий идентификатор (customerno) на сервере был равен 2,3 , 4 ..... для вновь вставленных данных на сервере.

здесь любой клиент может синхронизировать данные с сервером в любой момент времени.

Ответы [ 3 ]

3 голосов
/ 18 января 2011

Вы используете одно поле для двух вещей.Уникальная идентификация клиента и выяснение источника информации.

Вы можете использовать уникальный идентификатор в качестве первичного ключа и использовать другое поле для определения источника информации.

Использовать newid () в качестве ограничения по умолчанию для вашего первичного ключа.При репликации вы указываете GUID для использования, и он будет использоваться вместо newid ().

Изменить 1

Если у вас возникли проблемы при замене первичного ключа,Можно добавить столбец GUID в качестве ключа-кандидата.Тогда проблема будет в том, что логика репликации данных между серверами будет намного сложнее, если вам нужно обновить таблицы, которые имеют отношение к вашей таблице Customers.Сначала нужно вставить всех клиентов, а затем запросить таблицу клиентов, чтобы выяснить, какой идентификатор клиента FK следует использовать в связанных таблицах.

2 голосов
/ 18 января 2011

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

Если вы не можете поступить правильно, вы можете удалить столбец идентификации и сделать его целым. Затем вы можете создать свой собственный алгоритм автоинкремента, но следите за условиями гонки (т.е. не используйте MAX)

0 голосов
/ 18 января 2011

То, что вы хотите сделать, возможно, я думаю.Я не утверждаю, что это лучшая идея, но насколько я понимаю, следующее будет работать за счет блокировки всех изменений данных во время синхронизации.Очевидно, что в самом подходе есть проблемы, связанные с необходимостью точного прогнозирования максимально возможного числа клиентов и максимального количества вставок из каждого источника.

create table dbo.t (id int identity(1,1) primary key)

INSERT INTO dbo.t DEFAULT VALUES
INSERT INTO dbo.t DEFAULT VALUES
INSERT INTO dbo.t DEFAULT VALUES




--Do the Synch
BEGIN TRAN

DECLARE @MaxId int = (SELECT MAX(id) FROM t WITH (TABLOCK, REPEATABLEREAD) WHERE id<20000)
                      --Take a shared table lock to prevent any concurrent modifications

SET IDENTITY_INSERT t ON
INSERT INTO t(id) VALUES (20000)
SET IDENTITY_INSERT t OFF

DBCC CHECKIDENT ("dbo.t", RESEED, @MaxId)

COMMIT 
--Synch Finished

INSERT INTO dbo.t  DEFAULT VALUES /*Will have the value 4*/
SELECT * FROM dbo.t


DROP table dbo.t
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...