연습: 로컬 데이터베이스 캐시를 확장하여 양방향 동기화 지원

로컬 데이터베이스 캐시 항목을 프로젝트에 추가하여 로컬 SQL Server Compact 3.5 데이터베이스 캐시를 구성할 수 있고 Microsoft Synchronization Services for ADO.NET을 활성화하는 일련의 partial 클래스를 생성할 수 있습니다. Visual Studio에서는 partial 클래스를 생성하므로 동기화 기능을 추가하는 코드를 작성하는 동시에 데이터 동기화 구성 대화 상자에서 설정을 보고 변경하는 기능을 유지할 수 있습니다. partial 클래스에 대한 자세한 내용은 방법: 클래스를 부분 클래스로 분할(클래스 디자이너)을 참조하십시오.

기본적으로 데이터 동기화 구성 대화 상자에서는 다운로드에 대해서만 Synchronization Services를 구성할 수 있습니다. 즉 데이터 동기화를 구성한 후 Synchronize()를 호출하면 서버에서 클라이언트 데이터베이스로 변경 내용이 다운로드되기만 합니다. 동기화 코드를 확장하는 가장 일반적인 방법 중 하나는 양방향 동기화를 구성하는 것입니다. 이렇게 하면 클라이언트의 변경 내용을 서버로 업로드할 수 있습니다. 양방향 동기화를 사용하려면 생성된 코드를 다음과 같이 확장하는 것이 좋습니다.

  • 동기화 방향을 양방향으로 설정합니다.

  • 동기화 충돌을 처리하는 코드를 추가합니다.

  • 동기화 명령에서 서버 추적 열을 제거합니다.

사전 요구 사항

이 연습을 시작하려면 먼저 연습: 필요에 따라 연결되는 응용 프로그램 만들기를 완료해야 합니다. 해당 연습을 완료하면 Northwind Customers 테이블의 변경 내용을 SQL Server Compact 데이터베이스로 다운로드할 수 있는 Windows Forms 응용 프로그램과 로컬 데이터베이스 캐시 항목이 포함된 프로젝트가 만들어집니다. 이제 이 연습 솔루션을 로드하고 양방향 기능을 추가할 준비가 되었습니다.

참고

다음 지침처럼 컴퓨터에서 Visual Studio 사용자 인터페이스 요소 일부에 대한 이름이나 위치를 다르게 표시할 수 있습니다. 이러한 요소는 사용하는 Visual Studio 버전 및 설정에 따라 결정됩니다. 자세한 내용은 Visual Studio 설정을 참조하십시오.

OCSWalkthrough 솔루션을 열려면

  1. Visual Studio를 엽니다.

  2. 파일 메뉴에서 기존 솔루션 또는 프로젝트를 열고 OCSWalkthrough 솔루션을 찾습니다. 이 솔루션에 해당하는 파일은 OCSWalkthrough.sln입니다.

동기화 방향 설정

데이터 동기화 구성 대화 상자를 사용하여 SyncDirection() 속성을 DownloadOnly() 또는 Snapshot() 중 하나로 설정할 수 있습니다. 양방향 동기화를 사용하려면 변경 내용을 업로드하려는 각 테이블에 대해 SyncDirection() 속성을 Bidirectional()로 설정합니다.

동기화 방향을 설정하려면

  1. NorthwindCache.sync를 마우스 오른쪽 단추로 클릭하고 코드 보기를 클릭합니다. 처음 이 작업을 수행하면 솔루션 탐색기의 NorthwindCache.sync 노드 아래에 NorthwindCache 파일이 만들어집니다. 이 파일에는 NorthwindCacheSyncAgent partial 클래스가 들어 있는데 필요한 경우 다른 클래스를 추가할 수 있습니다.

  2. NorthwindCache 클래스 파일에서 NorthwindCacheSyncAgent.OnInitialized() 메서드가 다음 코드와 같아지도록 코드를 추가합니다.

    partial void OnInitialized()
    {
        this.Customers.SyncDirection = 
        Microsoft.Synchronization.Data.SyncDirection.Bidirectional;
    }
    
    Private Sub OnInitialized()
        Me.Customers.SyncDirection = 
        Microsoft.Synchronization.Data.SyncDirection.Bidirectional
    End Sub
    
  3. 코드 편집기에서 Form1을 엽니다.

  4. Form1 파일에서 업로드 및 다운로드 통계를 포함하도록 SynchronizeButton_Click 이벤트 처리기의 코드를 수정합니다.

    MessageBox.Show("Changes downloaded: " +
        syncStats.TotalChangesDownloaded.ToString() + 
        Environment.NewLine +
        "Changes uploaded: " + 
        syncStats.TotalChangesUploaded.ToString());
    
    MessageBox.Show("Changes downloaded: " & _
        syncStats.TotalChangesDownloaded.ToString & _
        Environment.NewLine & _
        "Changes uploaded: " & _
        syncStats.TotalChangesUploaded.ToString)
    

응용 프로그램 테스트

이제 동기화하는 동안 업로드와 다운로드를 모두 수행하도록 응용 프로그램이 구성되었습니다.

응용 프로그램을 테스트하려면

  1. F5 키를 누릅니다.

  2. 폼에서 레코드를 업데이트한 다음 저장 단추(도구 모음의 디스크 아이콘)를 클릭합니다.

  3. Synchronize Now를 클릭합니다.

  4. 동기화된 레코드에 대한 정보가 포함된 메시지 상자가 나타납니다. 서버에서는 변경된 내용이 없지만 통계에는 한 행이 업로드되고 한 행이 다운로드되었다는 내용이 표시됩니다. 추가 다운로드는 클라이언트의 변경 내용이 서버에서 적용된 후 다시 클라이언트에 전달되었기 때문에 발생합니다. 자세한 내용은 How to: Use a Custom Change Tracking System의 "Determining Which Client Made a Data Change"를 참조하십시오.

  5. 확인을 클릭하여 응용 프로그램이 실행 중인 상태로 메시지 상자를 닫습니다.

이제 클라이언트와 서버 양쪽에서 동일한 레코드를 변경하여 동기화 중 충돌(동시성 위반)이 발생하도록 합니다.

응용 프로그램을 테스트하고 충돌을 발생시키려면

  1. 폼에서 레코드를 업데이트한 다음 저장 단추를 클릭합니다.

  2. 응용 프로그램이 실행 중일 때 서버 탐색기/데이터베이스 탐색기 또는 다른 데이터베이스 관리 도구를 사용하여 서버 데이터베이스에 연결합니다.

  3. 충돌 해결의 기본 동작을 보기 위해 서버 탐색기/데이터베이스 탐색기에서 폼에서 업데이트한 레코드와 동일한 레코드를 다른 값으로 변경한 후 변경 내용을 커밋합니다. 그런 다음 수정된 행 밖으로 이동합니다.

  4. 폼으로 돌아가서 Synchronize Now를 클릭합니다.

  5. 응용 프로그램 표 및 서버 데이터베이스에서 업데이트를 확인합니다. 서버에서 업데이트한 내용이 클라이언트에서 업데이트한 내용을 덮어썼음을 알 수 있습니다. 충돌 해결 동작을 변경하는 방법은 이 항목의 다음 단원인 "동기화 충돌을 처리하는 코드 추가"를 참조하십시오.

동기화 충돌을 처리하는 코드 추가

Synchronization Services에서 충돌하는 행은 동기화 간에 클라이언트 및 서버에서 변경된 행입니다. Synchronization Services는 충돌을 검색 및 해결하는 데 사용할 수 있는 여러 가지 기능을 제공합니다. 이 단원에서는 클라이언트와 서버에서 동일한 행이 업데이트되어 발생하는 충돌을 처리하는 기본적인 코드를 추가합니다. 다른 종류의 충돌에는 한 데이터베이스에서 행이 삭제되고 다른 데이터베이스에서 업데이트되는 경우, 두 데이터베이스에 기본 키가 중복되는 행이 삽입되는 경우 등이 있습니다. 충돌 감지 및 해결에 대한 자세한 내용은 How to: Handle Data Conflicts and Errors를 참조하십시오.

참고

샘플 코드에서는 충돌을 처리하는 기본적인 예를 보여 줍니다. 충돌을 처리하는 방법은 비즈니스 논리 및 응용 프로그램의 요구 사항에 따라 다릅니다.

서버 ApplyChangeFailed 이벤트 및 클라이언트 ApplyChangeFailed 이벤트를 처리하는 코드를 추가하십시오. 이 이벤트는 충돌이나 오류로 인해 행을 적용할 수 없을 때 발생합니다. 이 이벤트를 처리하는 메서드에서는 충돌의 종류를 확인하고 클라이언트 변경 내용을 서버 데이터베이스에 적용하여 클라이언트 업데이트/서버 업데이트 충돌을 해결하도록 지정합니다. 서버 데이터베이스에 업데이트를 적용하는 동기화 명령에는 변경 내용을 적용할 시기를 인식하는 논리가 포함되어 있습니다. 이 명령은 이 항목의 다음 단원인 "동기화 명령에서 서버 추적 열 제거"에 있는 코드에 포함되어 있습니다.

충돌 처리 코드를 추가하기 위해 수행하는 단계는 사용하는 언어가 C#인지 Visual Basic인지에 따라 다릅니다.

충돌 처리를 추가하려면

  • C#을 사용하는 경우 NorthwindCache.cs 및 Form1.cs에 코드를 추가합니다. NorthwindCache.cs에서는 NorthwindCacheSyncAgent 클래스가 끝난 뒤에 다음 코드를 추가합니다.

    public partial class NorthwindCacheServerSyncProvider
    {
    
        partial void OnInitialized()
        {
            this.ApplyChangeFailed +=
                new System.EventHandler<Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs>
                (NorthwindCacheServerSyncProvider_ApplyChangeFailed);
        }
    
        private void NorthwindCacheServerSyncProvider_ApplyChangeFailed(object sender,
            Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs e)
        {
    
        if (e.Conflict.ConflictType ==
            Microsoft.Synchronization.Data.ConflictType.ClientUpdateServerUpdate)
            {
    
            // Resolve a client update / server update conflict by force writing
            // the client change to the server database.
            System.Windows.Forms.MessageBox.Show("A client update / server update conflict " +
                                                    "was detected at the server.");
            e.Action = Microsoft.Synchronization.Data.ApplyAction.RetryWithForceWrite;
    
            }
    
        }
    }
    
    public partial class NorthwindCacheClientSyncProvider
    {
    
        public void AddHandlers()
        {
            this.ApplyChangeFailed +=
                new System.EventHandler<Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs>
                (NorthwindCacheClientSyncProvider_ApplyChangeFailed);
        }
    
        private void NorthwindCacheClientSyncProvider_ApplyChangeFailed(object sender,
            Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs e)
        {
    
            if (e.Conflict.ConflictType ==
                Microsoft.Synchronization.Data.ConflictType.ClientUpdateServerUpdate)
            {
    
                // Resolve a client update / server update conflict by keeping the 
                // client change.
                e.Action = Microsoft.Synchronization.Data.ApplyAction.Continue;
    
            }
    
        }
    }
    

    Form1.cs에서는 이전 단계에서 NorthwindCache.cs에 추가한 AddHandler 메서드를 호출하도록 SynchronizeButton_Click 이벤트 처리기의 코드를 수정합니다.

    NorthwindCacheSyncAgent syncAgent = new NorthwindCacheSyncAgent();
    
    NorthwindCacheClientSyncProvider clientSyncProvider =
        (NorthwindCacheClientSyncProvider)syncAgent.LocalProvider;
    clientSyncProvider.AddHandlers();
    
    Microsoft.Synchronization.Data.SyncStatistics syncStats = 
        syncAgent.Synchronize();
    
  • Visual Basic을 사용하는 경우에는 NorthwindCache.vb에서 NorthwindCacheSyncAgent 클래스에 대한 End Class 문 뒤에 다음 코드를 추가합니다.

    Partial Public Class NorthwindCacheServerSyncProvider
    
        Private Sub NorthwindCacheServerSyncProvider_ApplyChangeFailed( _
            ByVal sender As Object, ByVal e As  _
            Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs) _
            Handles Me.ApplyChangeFailed
    
            If e.Conflict.ConflictType = _
                Microsoft.Synchronization.Data.ConflictType.ClientUpdateServerUpdate Then
    
                ' Resolve a client update / server update conflict by force writing
                ' the client change to the server database.
                MessageBox.Show("A client update / server update" & _
                    " conflict was detected at the server.")
                e.Action = Microsoft.Synchronization.Data.ApplyAction.RetryWithForceWrite
    
            End If
    
        End Sub
    
    End Class
    
    Partial Public Class NorthwindCacheClientSyncProvider
    
        Private Sub NorthwindCacheClientSyncProvider_ApplyChangeFailed( _
            ByVal sender As Object, ByVal e As  _
            Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs) _
            Handles Me.ApplyChangeFailed
    
            If e.Conflict.ConflictType = _
                Microsoft.Synchronization.Data.ConflictType.ClientUpdateServerUpdate Then
    
                ' Resolve a client update / server update conflict by keeping the 
                ' client change.
                e.Action = Microsoft.Synchronization.Data.ApplyAction.Continue
    
            End If
    
        End Sub
    
    End Class
    

충돌 해결을 동기화 및 확인하려면

  1. F5 키를 누릅니다.

  2. 폼에서 레코드를 업데이트한 다음 저장 단추를 클릭합니다.

  3. 서버 탐색기/데이터베이스 탐색기에서 폼에서 업데이트한 레코드와 동일한 레코드를 다른 값으로 변경한 후 변경 내용을 커밋합니다.

  4. 폼으로 돌아가서 Synchronize Now를 클릭합니다.

  5. 응용 프로그램 표 및 서버 데이터베이스에서 업데이트를 확인합니다. 클라이언트에서 업데이트한 내용이 서버에서 업데이트한 내용을 덮어썼음을 알 수 있습니다.

동기화 명령에서 서버 추적 열 제거

로컬 데이터베이스 캐시가 만들어지면 서버 데이터베이스에서 변경 내용을 추적하는 데 사용되는 열이 클라이언트로 다운로드됩니다. 이 연습에서 여기에 해당하는 열은 CreationDate 및 LastEditDate입니다. 양방향 동기화를 지원하고 클라이언트와 서버 데이터의 수렴을 보장하기 위해, 변경 내용을 서버 데이터베이스에 적용하는 SQL 명령에서 이 열을 제거합니다. 서버에서 변경 내용을 선택하여 클라이언트에 적용하는 명령에서 이 열을 제거할 수도 있지만 반드시 이와 같이 할 필요는 없습니다. 클라이언트 데이터베이스의 일부 스키마 변경 제한 사항 때문에 이러한 열은 삭제할 수 없습니다. 동기화 명령에 대한 자세한 내용은 How to: Specify Snapshot, Download, Upload, and Bidirectional Synchronization을 참조하십시오.

참고

SQL Server 2008 변경 추적을 사용하는 경우 추적 열이 테이블에 추가되지 않습니다. 이 경우 변경 내용을 서버에 적용하는 명령을 변경할 필요가 없습니다.

다음 코드에서는 Customers 테이블에 대한 SyncAdapter 개체의 속성으로 설정된 두 명령인 InsertCommand() 및 UpdateCommand() 속성을 다시 정의합니다. 데이터 동기화 구성 대화 상자에서 생성된 명령에는 CreationDate 및 LastEditDate 열에 대한 참조가 포함되어 있습니다. 다음 코드에서는 CustomersSyncAdapter 클래스의 OnInitialized 메서드에서 이 두 명령을 다시 정의합니다. DeleteCommand() 속성은 CreationDate 또는 LastEditDate 열에 영향을 미치지 않으므로 다시 정의되지 않습니다.

각 SQL 명령의 변수는 Synchronization Services, 클라이언트 및 서버 간 데이터 및 메타데이터를 전달하는 데 사용됩니다. 다음 세션 변수는 아래 명령에서 사용됩니다.

  • @sync\_row\_count: 서버에서 수행된 마지막 작업의 영향을 받은 행 수를 반환합니다. SQL Server 데이터베이스에서는 @@rowcount가 이 변수의 값을 제공합니다.

  • @sync\_force\_write: 충돌 또는 오류 때문에 실패한 변경 내용을 강제로 적용하는 데 사용됩니다.

  • @sync\_last\_received\_anchor: 세션 중 동기화할 변경 내용 집합을 정의하는 데 사용됩니다.

세션 변수에 대한 자세한 정보는 How to: Use Session Variables를 참조하십시오.

동기화 명령에서 추적 열 제거

  • NorthwindCache 클래스(NorthwindCache.vb 또는 NorthwindCache.cs)에서 NorthwindCacheServerSyncProvider 클래스의 End Class 문 뒤에 다음 코드를 추가합니다.

    public partial class CustomersSyncAdapter
    {
    
        partial void OnInitialized()
        {
    
        // Redefine the insert command so that it does not insert values 
        // into the CreationDate and LastEditDate columns.
        System.Data.SqlClient.SqlCommand insertCommand = new 
            System.Data.SqlClient.SqlCommand();
    
        insertCommand.CommandText = "INSERT INTO dbo.Customers ([CustomerID], [CompanyName], " +
            "[ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], " +
            "[Country], [Phone], [Fax] )" +
            "VALUES (@CustomerID, @CompanyName, @ContactName, @ContactTitle, @Address, @City, " +
            "@Region, @PostalCode, @Country, @Phone, @Fax) SET @sync_row_count = @@rowcount";
        insertCommand.CommandType = System.Data.CommandType.Text;
        insertCommand.Parameters.Add("@CustomerID", System.Data.SqlDbType.NChar);
        insertCommand.Parameters.Add("@CompanyName", System.Data.SqlDbType.NVarChar);
        insertCommand.Parameters.Add("@ContactName", System.Data.SqlDbType.NVarChar);
        insertCommand.Parameters.Add("@ContactTitle", System.Data.SqlDbType.NVarChar);
        insertCommand.Parameters.Add("@Address", System.Data.SqlDbType.NVarChar);
        insertCommand.Parameters.Add("@City", System.Data.SqlDbType.NVarChar);
        insertCommand.Parameters.Add("@Region", System.Data.SqlDbType.NVarChar);
        insertCommand.Parameters.Add("@PostalCode", System.Data.SqlDbType.NVarChar);
        insertCommand.Parameters.Add("@Country", System.Data.SqlDbType.NVarChar);
        insertCommand.Parameters.Add("@Phone", System.Data.SqlDbType.NVarChar);
        insertCommand.Parameters.Add("@Fax", System.Data.SqlDbType.NVarChar);
        insertCommand.Parameters.Add("@sync_row_count", System.Data.SqlDbType.Int);
        insertCommand.Parameters["@sync_row_count"].Direction = 
            System.Data.ParameterDirection.Output;
    
        this.InsertCommand = insertCommand;
    
    
        // Redefine the update command so that it does not update values 
        // in the CreationDate and LastEditDate columns.
        System.Data.SqlClient.SqlCommand updateCommand = new System.Data.SqlClient.SqlCommand();
    
        updateCommand.CommandText = "UPDATE dbo.Customers SET [CompanyName] = @CompanyName, [ContactName] " +
            "= @ContactName, [ContactTitle] = @ContactTitle, [Address] = @Address, [City] " +
            "= @City, [Region] = @Region, [PostalCode] = @PostalCode, [Country] = @Country, " +
            "[Phone] = @Phone, [Fax] = @Fax " +
            "WHERE ([CustomerID] = @CustomerID) AND (@sync_force_write = 1 " +
            "OR ([LastEditDate] <= @sync_last_received_anchor)) SET @sync_row_count = @@rowcount";
        updateCommand.CommandType = System.Data.CommandType.Text;
        updateCommand.Parameters.Add("@CompanyName", System.Data.SqlDbType.NVarChar);
        updateCommand.Parameters.Add("@ContactName", System.Data.SqlDbType.NVarChar);
        updateCommand.Parameters.Add("@ContactTitle", System.Data.SqlDbType.NVarChar);
        updateCommand.Parameters.Add("@Address", System.Data.SqlDbType.NVarChar);
        updateCommand.Parameters.Add("@City", System.Data.SqlDbType.NVarChar);
        updateCommand.Parameters.Add("@Region", System.Data.SqlDbType.NVarChar);
        updateCommand.Parameters.Add("@PostalCode", System.Data.SqlDbType.NVarChar);
        updateCommand.Parameters.Add("@Country", System.Data.SqlDbType.NVarChar);
        updateCommand.Parameters.Add("@Phone", System.Data.SqlDbType.NVarChar);
        updateCommand.Parameters.Add("@Fax", System.Data.SqlDbType.NVarChar);
        updateCommand.Parameters.Add("@CustomerID", System.Data.SqlDbType.NChar);
        updateCommand.Parameters.Add("@sync_force_write", System.Data.SqlDbType.Bit);
        updateCommand.Parameters.Add("@sync_last_received_anchor", System.Data.SqlDbType.DateTime);
        updateCommand.Parameters.Add("@sync_row_count", System.Data.SqlDbType.Int);
        updateCommand.Parameters["@sync_row_count"].Direction = 
            System.Data.ParameterDirection.Output;
    
        this.UpdateCommand = updateCommand;
    
        }
    }
    
    Partial Public Class CustomersSyncAdapter
        Private Sub OnInitialized()
    
            ' Redefine the insert command so that it does not insert values 
            ' into the CreationDate and LastEditDate columns.
            Dim insertCommand As New System.Data.SqlClient.SqlCommand
            With insertCommand
                .CommandText = "INSERT INTO dbo.Customers ([CustomerID], [CompanyName], " & _
                    "[ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], " & _
                    "[Country], [Phone], [Fax] )" & _
                    "VALUES (@CustomerID, @CompanyName, @ContactName, @ContactTitle, @Address, @City, " & _
                    "@Region, @PostalCode, @Country, @Phone, @Fax) SET @sync_row_count = @@rowcount"
                .CommandType = System.Data.CommandType.Text
                .Parameters.Add("@CustomerID", System.Data.SqlDbType.NChar)
                .Parameters.Add("@CompanyName", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@ContactName", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@ContactTitle", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@Address", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@City", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@Region", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@PostalCode", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@Country", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@Phone", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@Fax", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@sync_row_count", System.Data.SqlDbType.Int)
                .Parameters("@sync_row_count").Direction = ParameterDirection.Output
            End With
    
            Me.InsertCommand = insertCommand
    
    
            ' Redefine the update command so that it does not update values 
            ' in the CreationDate and LastEditDate columns.
            Dim updateCommand As New System.Data.SqlClient.SqlCommand
            With updateCommand
                .CommandText = "UPDATE dbo.Customers SET [CompanyName] = @CompanyName, [ContactName] " & _
                    "= @ContactName, [ContactTitle] = @ContactTitle, [Address] = @Address, [City] " & _
                    "= @City, [Region] = @Region, [PostalCode] = @PostalCode, [Country] = @Country, " & _
                    "[Phone] = @Phone, [Fax] = @Fax " & _
                    "WHERE ([CustomerID] = @CustomerID) AND (@sync_force_write = 1 " & _
                    "OR ([LastEditDate] <= @sync_last_received_anchor)) SET @sync_row_count = @@rowcount"
                .CommandType = System.Data.CommandType.Text
                .Parameters.Add("@CompanyName", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@ContactName", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@ContactTitle", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@Address", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@City", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@Region", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@PostalCode", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@Country", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@Phone", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@Fax", System.Data.SqlDbType.NVarChar)
                .Parameters.Add("@CustomerID", System.Data.SqlDbType.NChar)
                .Parameters.Add("@sync_force_write", System.Data.SqlDbType.Bit)
                .Parameters.Add("@sync_last_received_anchor", System.Data.SqlDbType.DateTime)
                .Parameters.Add("@sync_row_count", System.Data.SqlDbType.Int)
                .Parameters("@sync_row_count").Direction = ParameterDirection.Output
            End With
    
            Me.UpdateCommand = updateCommand
    
        End Sub
    
    End Class
    

응용 프로그램 테스트

추적 열 업데이트를 동기화 및 확인하려면

  1. F5 키를 누릅니다.

  2. 폼에서 LastEditDate 열의 값을 변경하여 레코드를 업데이트한 다음 저장 단추를 클릭합니다.

  3. 폼으로 돌아가서 Synchronize Now를 클릭합니다.

  4. 응용 프로그램 표 및 서버 데이터베이스에서 업데이트를 확인합니다. 서버의 열 값이 클라이언트에서 업데이트한 내용을 덮어썼음을 알 수 있습니다. 업데이트 프로세스는 다음과 같습니다.

    1. Synchronization Services는 클라이언트에서 행이 변경되었음을 파악합니다.

    2. 동기화를 수행하는 동안 해당 행이 업로드되어 서버 데이터베이스의 테이블에 적용됩니다. 그러나 추적 열은 update 문에 포함되지 않습니다. Synchronization Services에서는 테이블에 대한 "더미 업데이트"를 효율적으로 수행합니다.

    3. 이제 이 행은 클라이언트로 다시 전달되는데 이때 서버에서 변경 내용을 선택하는 명령에 추적 열이 포함되게 됩니다. 따라서 서버의 값이 클라이언트에서 변경된 내용을 덮어쓰게 됩니다.

다음 단계

이 연습에서는 기본 충돌 처리를 포함하여 양방향 동기화를 구성했으며 클라이언트 데이터베이스에 서버 추적 열이 포함되었을 때 발생할 수 있는 잠재적인 문제에 대해 알아 보았습니다. partial 클래스를 사용하면 로컬 데이터베이스 캐시 코드를 다른 중요한 기능을 수행하도록 확장할 수 있습니다. 예를 들어 서버 데이터베이스에서 변경 내용을 선택하는 SQL 명령을 다시 정의하여 데이터가 클라이언트로 다운로드될 때 이를 필터링할 수 있습니다. 이 설명서의 방법 항목을 통해 응용 프로그램의 요구 사항에 맞도록 동기화 코드를 추가하거나 변경하는 방법을 이해하는 것이 좋습니다. 자세한 내용은 How to Program Common Client and Server Synchronization Tasks를 참조하십시오.

참고 항목

개념

필요에 따라 연결되는 응용 프로그램 개요

기타 리소스

일반적인 클라이언트 및 서버 동기화 태스크 프로그래밍

응용 프로그램 개발용 도구