2011-01-18 4 views
-1

현재 프로젝트에 SQL Server 2008, Visual Studio 2008, linq, ado.net을 사용하고 있습니다. 이 프로젝트는 웹 및 데스크톱에서 구현됩니다.identity_insert 및 동기화 문제

이제 내 문제는 웹 데이터베이스와 데스크톱 db 간의 데이터 동기화입니다.

여기

동기화는 다음과 같다 : 클라이언트에 삽입

  1. 새로운 데이터는 서버에 동기화됩니다.
  2. 클라이언트의 업데이트 된 데이터가 서버에 동기화됩니다.

여기 내 테이블 구조를 보여 드리겠습니다.

우리가 내 테이블 이름을 가정 해 봅시다 필드

고객
...................
customerno, BIGINT, 기본 키와 "고객"입니다 , null가 아닌, 정체성 사실
FIRSTNAME ...
LASTNAME, ...

지금

내가 클라이언트에서 동일한 테이블을해야하지만, 기본 키 정체성 20000이 시작됩니다 (1부터 시작) 기본 키 ID는 클라이언트 시스템의 수에 따라 다릅니다. 표 1 개 레코드

서버가 customerno 1로 시작 = 다음과 같은 시나리오를 생각해 보자
CLIENT1 = customerno 테이블이 개 레코드, 20000로 시작
CLIENT2 = customerno 테이블

3 개 레코드, 30000로 시작

이제 LINQ 그다지지지 IDENTITY_INSERT, IM 사용 ado.net으로 다음 코드

 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(); 

를 사용 CLIENT1에서 동기화를 누르면

012,351,

내 코드에서 먼저 identity_insert를 on으로 설정하고 데이터를 삽입 한 다음 마지막으로 identity_insert를 설정 해제하십시오.

여기 내 문제는 데이터가 client1에서 동기화 된 후 이고 두 개의 레코드가 customerno가있는 서버에 20001,20002로 삽입됩니다. http://msdn.microsoft.com/en-us/library/ms188059.aspx

서버 customerno 컬럼의 신원에 따라

(이 경우는 20002이 될 것이다)를 최대 값으로 설정된다. 내가 서버에 데이터를 삽입 할 때

은 그래서 지금, 내가 최대 값을 적용하려면 서버 ID 열을 원하는 그나마 여기 20003.

로 customerno에 삽입합니다.

위의 경우를 고려하여 동기화하기 전에 서버에 레코드가 1 개 있고 ID가 1이므로 동기화 (하나 이상의 클라이언트) 후 서버의 다음 ID (사용자 정의)를 2로 설정하고, 3,4 ..... 서버에 새로 삽입 된 데이터입니다.

여기서 모든 클라이언트는 언제든지 서버와 데이터를 동기화 할 수 있습니다.

답변

3

두 필드에 하나의 필드를 사용하고 있습니다. 고객을 고유하게 식별하고 정보의 출처를 파악합니다.

uniqueidentifier를 기본 키로 사용하고 다른 필드를 사용하여 정보의 출처를 결정할 수 있습니다.

기본 키의 기본 제약 조건으로 newid()를 사용하십시오. 복제 할 때 사용할 GUID를 지정하면 newid() 대신이 GUID가 사용됩니다.

편집 한

당신은 문제가 기본 키 당신이 후보 키로 GUID 열을 추가 할 수 있습니다 교체가있는 경우. 문제는 Customers 테이블과의 관계가있는 테이블을 업데이트해야하는 경우 서버간에 데이터를 복제하는 논리가 훨씬 복잡해질 것이라는 점입니다. 먼저 모든 고객을 삽입 한 다음 Customers 테이블을 쿼리하여 관련 테이블에서 사용해야하는 FK CustomerID를 파악해야합니다.

+0

GUID가 좋으므로 새 열을 사용하십시오. 그럼 내 데이터베이스에있는 모든 테이블을 변경해야합니다. – Harsha

+0

데이터베이스에있는 고객과 관련된 모든 테이블을 변경하는 데 문제가있는 경우 수정 된 답변 –

2

아주 나쁜 장소에 있습니다. 서로 게이트 범위를 지정하려면 ID 열을 사용할 수 없습니다. 이 문제를 포기하고 replication 기술이 내장되어있는 것은 아마도 옳은 일입니다.

올바른 작업을 수행 할 수없는 경우 ID 열을 삭제하고 int로 만들 수 있습니다. 그렇다면 자신 만의 자동 증가 알고리즘을 만들 수 있지만 경쟁 조건 (예 : MAX는 사용하지 않음)을주의 할 수 있습니다.

0

내가 원하는 것은 가능하다고 생각합니다. 나는 이것이 최선의 아이디어라고 제안하는 것이 아니라, 내가 볼 수있는 한, 동기화가 진행되는 동안 모든 데이터 변경을 막을 수있는 다음 작업이 효과가 있다는 것을 알 수 있습니다. 클라이언트의 가능한 최대 수와 각 소스의 최대 삽입 수를 정확하게 예측할 필요가 있다는 점에서 분명히 접근 자체에는 고유 한 문제가 있습니다.

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 
+0

좋은 해결책이지만 테이블을 다시 시드 할 수 있습니까? 다른 사람들은 – Harsha

+0

@ Harsha에 identity_insert를 사용하지 않고 데이터를 삽입 할 것입니다. 유일한 방법은 동기화하는 동안 동시 삽입을 차단하는 것입니다. 그렇지 않으면 현재 시드보다 큰 ID를 가진 레코드를 삽입하자마자 시드가 증가하고 새로운 시드 값을 사용하여 이러한 동시 삽입이 끝날 것이라고 상상해보십시오. 이 동시성 부족이 용납되지 않는 경우 다른 대답에서 제안 된대로 스키마를 변경해야합니다. –