【发布时间】:2014-02-06 19:37:21
【问题描述】:
我正在使用 Microsoft Sync Framework v2.1 来同步两个数据库,即从远程(ms sql server 2012)到本地(ms sql server express 2008 R2)。可以在本地数据库上成功创建表,但是由于以下错误导致数据未同步:
当前操作无法完成,因为数据库未配置为同步,或者您没有同步配置表的权限。
但是,在同步2个本地数据库时(使用ms sql server express 2008 R2),同步成功。
有人对可能出现的问题有什么建议吗?
谢谢。
代码
以下是主要形式:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// create a connection to the SyncExpressDB database
string clientConn = ConfigurationManager.ConnectionStrings["ianConnection"].ConnectionString;
// create a connection to the SyncDB server database
string serverConn = ConfigurationManager.ConnectionStrings["arvixeConnection"].ConnectionString;
Utilities.Synchronisation.Db.DBSynchroniser dbSync = new DBSynchroniser(clientConn, serverConn);
dbSync.ProvisionSyncScope("TestScope", "Products", DBSyncSide.Both);
dbSync.Sync(Microsoft.Synchronization.SyncDirectionOrder.Download, "TestScope");
label1.Text = "Sync Done !!!";
}
}
以下是同步类
public class DBSynchroniser
{
SqlConnection clientConnection;
SqlConnection serverConnection;
SyncOrchestrator syncOrchestrator;
private EventHandler<DbApplyChangeFailedEventArgs> changeFailedHandler;
public EventHandler<DbApplyChangeFailedEventArgs> ChangeFailedHandler
{
get { return changeFailedHandler; }
set { changeFailedHandler = value; }
}
public DBSynchroniser(string clientConn, string serverConn)
{
clientConnection = new SqlConnection(clientConn);
serverConnection = new SqlConnection(serverConn);
syncOrchestrator = new SyncOrchestrator();
changeFailedHandler = new EventHandler<DbApplyChangeFailedEventArgs>(ApplyChangeFailed);
}
public void ProvisionSyncScope(string syncScopeName, string tableName, DBSyncSide syncSide)
{
ProvisionSyncScope(syncScopeName, new List<string>(new string[] { tableName }), syncSide);
}
public void ProvisionSyncScope(string syncScopeName, List<string> tableNames, DBSyncSide syncSide)
{
DbSyncScopeDescription scopeDesc;
// define a new scope
scopeDesc = new DbSyncScopeDescription(syncScopeName);
scopeDesc.UserComment = "This is to test the sync class";
foreach (string name in tableNames)
{
// get the description of the table name
// and add the table description to the sync scope definition
scopeDesc.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable(name, serverConnection));
}
// create a server scope provisioning object based on the ProductScope
SqlSyncScopeProvisioning serverProvision = new SqlSyncScopeProvisioning(serverConnection, scopeDesc);
SqlSyncScopeProvisioning clientProvision = new SqlSyncScopeProvisioning(clientConnection, scopeDesc);
// skipping the creation of table since table already exists on server
serverProvision.SetCreateTableDefault(DbSyncCreationOption.CreateOrUseExisting);
clientProvision.SetCreateTableDefault(DbSyncCreationOption.CreateOrUseExisting);
// start the provisioning process
switch (syncSide)
{
case DBSyncSide.Client:
clientProvision.Apply();
break;
case DBSyncSide.Server:
serverProvision.Apply();
break;
case DBSyncSide.Both:
serverProvision.Apply();
clientProvision.Apply();
break;
default:
break;
}
}
public void DeprovisionScope(string scopeName, DBSyncSide syncSide)
{
SqlSyncScopeDeprovisioning clientSqlDepro = new SqlSyncScopeDeprovisioning(clientConnection);
SqlSyncScopeDeprovisioning serverSqlDepro = new SqlSyncScopeDeprovisioning(serverConnection);
// First save the deprovisioning script so it can be run on other SQL Server client databases.
// This step is optional.
//File.WriteAllText("SampleDeprovisionScript.txt", clientSqlDepro.ScriptDeprovisionScope(scopeName));
// Remove the scope.
switch (syncSide)
{
case DBSyncSide.Client:
clientSqlDepro.DeprovisionScope(scopeName);
break;
case DBSyncSide.Server:
serverSqlDepro.DeprovisionScope(scopeName);
break;
case DBSyncSide.Both:
clientSqlDepro.DeprovisionScope(scopeName);
serverSqlDepro.DeprovisionScope(scopeName);
break;
default:
break;
}
}
public DBSyncOperationStatistics Sync(SyncDirectionOrder direction, string syncScopeName)
{
// set local provider of orchestrator to a sync provider associated with the
// MySyncScope in the client database
syncOrchestrator.LocalProvider = new SqlSyncProvider(syncScopeName, clientConnection); //check objectPrefix and schema
// set the remote provider of orchestrator to a server sync provider associated with
// the MySyncScope in the server database
syncOrchestrator.RemoteProvider = new SqlSyncProvider(syncScopeName, serverConnection); //check objectPrefix and schema
// set the direction of sync session to Upload and Download
syncOrchestrator.Direction = direction;
// subscribe for errors that occur when applying changes to the client
((SqlSyncProvider)syncOrchestrator.LocalProvider).ApplyChangeFailed += changeFailedHandler;
// execute the synchronization process
DBSyncOperationStatistics syncStats = new DBSyncOperationStatistics(syncOrchestrator.Synchronize());
//return statistics of synchronisation
return syncStats;
}
private void ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
{
throw e.Error;
}
~DBSynchroniser()
{
if (clientConnection.State == System.Data.ConnectionState.Open)
{
clientConnection.Close();
clientConnection.Dispose();
}
if (serverConnection.State == System.Data.ConnectionState.Open)
{
serverConnection.Close();
serverConnection.Dispose();
}
}
}
【问题讨论】:
-
您是否在服务器上配置数据库?我通常在将数据移动到服务器后执行 PerformPostRestoreFixup,然后在服务器上配置数据库。
-
您使用的是非 dbo 架构吗?
-
我不是数据库专家,但我认为我使用的是 dbo 模式,因为在每个表名前面都有 dbo(例如:dbo.Users、dbo.Towns) .关于 PeterJ 的问题,我认为我正在配置,因为在两个数据库中都创建了所有必需的字段,例如 schema.info、tableName.tracking 等。但是,我无法将数据从远程数据库传输到本地数据库。在下一条评论中,我将发布用于同步的代码
-
我已经编辑了帖子本身,我添加了用于同步的代码。问题可能是未指定的 ObjectPrefix 和架构吗?我在我的代码中做了评论,但我不知道什么是 ObjectPrefix 请参阅我帖子中的 CODE 部分。谢谢。
-
在 scope_info 表中,您在其中看到您的范围名称吗?同样,为什么每次同步时都要进行配置?您应该只配置一次范围。
标签: sql sql-server database synchronization microsoft-sync-framework