2013-06-24 180 views
0

我新的Microsoft同步框架,並與微軟下面的示例IM測試(見http://msdn.microsoft.com/en-us/library/ff928758.aspx):微軟同步框架衝突事件不火

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data.SqlClient; 
using Microsoft.Synchronization; 
using Microsoft.Synchronization.Data; 
using Microsoft.Synchronization.Data.SqlServer; 
using Microsoft.Synchronization.Data.SqlServerCe; 

namespace ExecuteExpressSync 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      SqlConnection clientConn = new SqlConnection(@"Data Source=.\SQLCLIENT; Initial Catalog=SyncExpressDB; Trusted_Connection=Yes"); 

      SqlConnection serverConn = new SqlConnection("Data Source=localhost\\SQLEXPRESS; Initial Catalog=SyncDB; Integrated Security=True"); 

      // create the sync orhcestrator 
      SyncOrchestrator syncOrchestrator = new SyncOrchestrator(); 

      // set local provider of orchestrator to a sync provider associated with the 
      // ProductsScope in the SyncExpressDB express client database 
      syncOrchestrator.LocalProvider = new SqlSyncProvider("ProductsScope", clientConn); 


      // set the remote provider of orchestrator to a server sync provider associated with 
      // the ProductsScope in the SyncDB server database 
      syncOrchestrator.RemoteProvider = new SqlSyncProvider("ProductsScope", serverConn); 


      // set the direction of sync session to Upload and Download 
      syncOrchestrator.Direction = SyncDirectionOrder.UploadAndDownload; 


      // subscribe for errors that occur when applying changes to the client 
      ((SqlCeSyncProvider)syncOrchestrator.RemoteProvider).ApplyChangeFailed += new EventHandler<DbApplyChangeFailedEventArgs>(Program_ApplyChangeFailed); 
      ((SqlCeSyncProvider)syncOrchestrator.LocalProvider).ApplyChangeFailed += new EventHandler<DbApplyChangeFailedEventArgs>(Program_ApplyChangeFailed); 

      // 
      makeConflict(clientConn, "999"); 
      makeConflict(serverConn, "666"); 

      // execute the synchronization process 
      SyncOperationStatistics syncStats = syncOrchestrator.Synchronize(); 

      // print statistics 
      Console.WriteLine("Start Time: " + syncStats.SyncStartTime); 
      Console.WriteLine("Total Changes Uploaded: " + syncStats.UploadChangesTotal); 
      Console.WriteLine("Total Changes Downloaded: " + syncStats.DownloadChangesTotal); 
      Console.WriteLine("Download failed: " + syncStats.DownloadChangesFailed); 
      Console.WriteLine("Upload Changes failed: " + syncStats.UploadChangesFailed); 
      Console.WriteLine("Complete Time: " + syncStats.SyncEndTime); 
      Console.WriteLine(String.Empty); 

      Console.ReadLine(); 

     } 

     static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e) 
     { 
      // display conflict type 
      Console.WriteLine(e.Conflict.Type); 

      // display error message 
      Console.WriteLine(e.Error); 
     } 

     private static void makeConflict(SqlConnection nodeConn, String price) 
     { 
      int rowCount = 0; 

      using (nodeConn) 
      { 
       SqlCommand sqlCommand = nodeConn.CreateCommand(); 

       sqlCommand.CommandText = "UPDATE Products SET ListPrice = " + price + " WHERE Name = 'PCClient' "; 


       nodeConn.Open(); 
       rowCount = sqlCommand.ExecuteNonQuery(); 
       nodeConn.Close(); 

      } 
     } 

    } 
} 

我有兩個SQL-Server實例(SQLCLIENT和SQLEXPRESS )在我的本地PC上測試環境。我的問題是ApplyChangeFailed事件不會觸發,儘管我通過調用makeConflict()來創建衝突,makeConflict()一次爲產品表中的一行執行UPDATE,一次爲服務器和客戶端執行UPDATE。結果是服務器或客戶端都會贏,具體取決於SyncDirectionOrder屬性。

我在做什麼錯了?

+0

在調用同步之前,您是否可以確認正在提交的更新正在提交?或者檢查_tracking表是否實際更新? – JuneT

+0

是的,更新將在調用同步之前提交。 _tracking表中的「last_change_」時間戳已被更新。如果我在Management Studio中手動更改值或調用makeConflict(),也沒有區別。行爲是一樣的。當將SyncDirectionOrder設置爲UploadAndDownload時,服務器獲勝,通過DownloadAndUpload,客戶端獲勝。 – user2516796

回答

0

它的工作原理! 我想我需要一個專用的服務器是對的。 我在兩臺客戶端主機上更改了同一行,並在同步第二個客戶端後發生了「localupdateremoteupdate」衝突。

1

改變這一點:

((SqlCeSyncProvider)syncOrchestrator

這樣:

((SqlSyncProvider)syncOrchestrator

您使用的SqlSyncProvider,而不是SqlCeSyncProvider

+0

哦,對不起,這只是暫時的測試。通常我使用SQLSyncProvider。 – user2516796

+0

你對測試有什麼意義?那麼你的實際代碼是什麼? – JuneT

+0

上面的代碼中的代碼不是實際的狀態。我在使用SQLCeSyncProvider而不是SQLSyncProvider進行測試時複製了代碼。您只需將SQLCeSyncProvider更改爲SQLSyncProvider,即可獲得我的實際代碼。對不起,混亂! – user2516796

0

爲了避免進一步的混淆,這裏是實際的代碼。問題仍然存在。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data.SqlClient; 
using Microsoft.Synchronization; 
using Microsoft.Synchronization.Data; 
using Microsoft.Synchronization.Data.SqlServer; 
using Microsoft.Synchronization.Data.SqlServerCe; 

namespace ExecuteExpressSync 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      SqlConnection clientConn = new SqlConnection(@"Data Source=.\SQLCLIENT; Initial Catalog=SyncExpressDB; Trusted_Connection=Yes"); 

      SqlConnection serverConn = new SqlConnection("Data Source=localhost\\SQLEXPRESS; Initial Catalog=SyncDB; Integrated Security=True"); 

      // create the sync orhcestrator 
      SyncOrchestrator syncOrchestrator = new SyncOrchestrator(); 

      // set local provider of orchestrator to a sync provider associated with the 
      // ProductsScope in the SyncExpressDB express client database 
      syncOrchestrator.LocalProvider = new SqlSyncProvider("ProductsScope", clientConn); 


      // set the remote provider of orchestrator to a server sync provider associated with 
      // the ProductsScope in the SyncDB server database 
      syncOrchestrator.RemoteProvider = new SqlSyncProvider("ProductsScope", serverConn); 


      // set the direction of sync session to Upload and Download 
      syncOrchestrator.Direction = SyncDirectionOrder.UploadAndDownload; 


      // subscribe for errors that occur when applying changes to the client 
      ((SqlSyncProvider)syncOrchestrator.RemoteProvider).ApplyChangeFailed += new EventHandler<DbApplyChangeFailedEventArgs>(Program_ApplyChangeFailed); 
      ((SqlSyncProvider)syncOrchestrator.LocalProvider).ApplyChangeFailed += new EventHandler<DbApplyChangeFailedEventArgs>(Program_ApplyChangeFailed); 

      // 
      makeConflict(clientConn, "999"); 
      makeConflict(serverConn, "666"); 

      // execute the synchronization process 
      SyncOperationStatistics syncStats = syncOrchestrator.Synchronize(); 

      // print statistics 
      Console.WriteLine("Start Time: " + syncStats.SyncStartTime); 
      Console.WriteLine("Total Changes Uploaded: " + syncStats.UploadChangesTotal); 
      Console.WriteLine("Total Changes Downloaded: " + syncStats.DownloadChangesTotal); 
      Console.WriteLine("Download failed: " + syncStats.DownloadChangesFailed); 
      Console.WriteLine("Upload Changes failed: " + syncStats.UploadChangesFailed); 
      Console.WriteLine("Complete Time: " + syncStats.SyncEndTime); 
      Console.WriteLine(String.Empty); 

      Console.ReadLine(); 

     } 

     static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e) 
     { 
      // display conflict type 
      Console.WriteLine(e.Conflict.Type); 

      // display error message 
      Console.WriteLine(e.Error); 
     } 

     private static void makeConflict(SqlConnection nodeConn, String price) 
     { 
      int rowCount = 0; 

      using (nodeConn) 
      { 
       SqlCommand sqlCommand = nodeConn.CreateCommand(); 

       sqlCommand.CommandText = "UPDATE Products SET ListPrice = " + price + " WHERE Name = 'PCClient' "; 


       nodeConn.Open(); 
       rowCount = sqlCommand.ExecuteNonQuery(); 
       nodeConn.Close(); 

      } 
     } 

    } 
} 
+0

也許我找到了問題:我嘗試在一臺服務器和一臺客戶機之間進行同步。根據MSDN-HowTo衝突處理(http://msdn.microsoft.com/en-us/library/cc761628.aspx),如果兩個或多個客戶端更改了相同的數據集,則會發生衝突。這似乎是在這種情況下,服務器不能改變數據集!? 這將暗示我需要一個專用服務器主機和兩個客戶端用於我的場景。我對嗎? – user2516796

+0

不是。它與專用服務器無關。您使用的同步提供商是點對點提供商,沒有客戶或服務器的概念,只有對等或副本,來源和目的地。 – JuneT