原谅我对Microsoft Sync Framework的无知,因为我对它很陌生。但无论如何,我正在尝试开发一个自定义的仅上载同步过程,从Sql CE到与IBM websphere MQ接口的自定义InsertCommand派生类。
public class MyServerSyncProvider : DbServerSyncProvider
{
#region Constructors
public MyServerSyncProvider()
{
base.Connection = CreateConnection();
base.SyncAdapters.Add(MySyncAdapter);
}
}
class MySyncAdapter : SyncAdapter
{
public MySyncAdapter(DbServerSyncProvider syncProvider)
{
base.TableName = "MyTable";
base.InsertCommand = SyncHelper.CreateStoredProcCommand(syncProvider.Connection, "Queue Message Start:");
var parm1 = base.InsertCommand.CreateParameter();
parm1.ParameterName = "@parm1";
parm1.Direction = ParameterDirection.Input;
parm1.DbType = DbType.DateTime;
parm1.SourceColumn = "source_column";
base.InsertCommand.Parameters.Add(parm1);
/////More Input parms
var rowCount = base.InsertCommand.CreateParameter();
rowCount.ParameterName = "@sync_row_count";
rowCount.Direction = ParameterDirection.Output;
rowCount.DbType = DbType.Int16;
rowCount.SourceColumn = Microsoft.Synchronization.Data.SyncSession.SyncRowCount;
base.InsertCommand.Parameters.Add(rowCount);
}
}
这是通过覆盖ExecuteNonQuery方法来写入队列来实现的(我们从命令text / parameters创建消息)。
Public Overrides Function ExecuteNonQuery() As Integer
Dim mqConnectionObject As MQServerConnection = DirectCast(Me.Connection, MQServerConnection)
''get an instance of the MQServerFacade
Dim mqServerFacade As MQTEPServerFacade = DirectCast(Me.Connection, MQServerConnection).MQServer
If Me.Timeout > 0 Then
mqServerFacade.Timeout = Me.Timeout
End If
Me.Parameters("@sync_row_count").Value = 0
Try
mqServerFacade.PutOnRequestQueue(CreateXmlDocumentForMQMessage())
Me.Parameters("@sync_row_count").Value = 1
Return 1
Catch ex As Exception
_logger.Write(TraceEventType.[Error], ex.Message)
Return -1
End Try
End Function
奇怪的是,这一切都奏效了。同步时,ApplyChanges函数正在创建新的MQ“连接”。然后,它遍历更改集中的每一行,正确填充参数并将消息放入队列。 (仅供参考,同步过程会抓取客户端表中的所有行,然后在同步完成后删除行。我认为不需要任何锚点。)
我遇到的问题是它没有完全正确地跟踪更改。例如,不会捕获可能在插入进程上发生的任何错误。正如您在上面的示例中所看到的,我必须将事务封装在try块中,否则同步将完全停止。我希望抓住错误,然后让进程点击ApplyChangeFailed监听器,然后继续下一行(见下文)。
public class MySynchronizationService : DbSyncProviderService<MyServerSyncProvider>
{
private static readonly string category = "MySynchronizationService";
public MySynchronizationService()
{
this._serverSyncProvider.ApplyChangeFailed += new EventHandler<Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs>(_serverSyncProvider_ApplyChangeFailed);
}
void _serverSyncProvider_ApplyChangeFailed(object sender, Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs e)
{
e.Action = Microsoft.Synchronization.Data.ApplyAction.Continue;
}
public override Microsoft.Synchronization.Data.SyncContext ApplyChanges(Microsoft.Synchronization.Data.SyncGroupMetadata groupMetaData, System.Data.DataSet changeSet, Microsoft.Synchronization.Data.SyncSession syncSession)
{
SetupContext(category, "ApplyChanges");
Logger.Write(TraceEventType.Information, string.Format("Applying changes for {0} synchronization group",groupMetaData.GroupName));
return base.ApplyChanges(groupMetaData, changeSet, syncSession);
}
}
我听说@sync_row_count参数与此有关,但它似乎没有做任何事情。我的try catch确实阻止了行被放到队列中,但我没有得到任何反馈(syncStatistics只是说所有行都成功应用了)。
此外,同步过程在计时器上,在下一次尝试时,它会尝试同步上一批中的相同行。幸运的是,行状态设置为“已添加”,因此不再为这些行调用我的ExecuteNonQuery。这进一步巩固了插入数据(放入队列)以及Microsoft Sync Framework如何跟踪更改/错误之间存在一些脱节。
您将获得的任何帮助都将受到赞赏。我知道这个解决方案有点“开箱即用”,因为据我所知,Microsoft Sync Framework通常是数据库到数据库或文件到文件(而IBM MQ显然不是数据库),但如上所述,该过程是“工作”但我显然对我实施的内容感到不自在。