我正在编写一个n层应用程序,它将Sync Framework v2.1与WCF Web服务结合使用。我的代码基于此示例:Database-Sync
同步似乎没有问题。但是,当我添加批处理功能时,我得到的错误证明难以调试。
在解决方案的客户端部分(WPF应用程序)中,我有一个继承自KnowledgeSyncProvider的虚拟类。它还实现了IDisposable接口。我使用这个类来调用我编写的WCF服务并在那里使用同步功能。当同步代码运行时(调用orchestrator.Synchronize()),一切似乎都正常工作,并且EndSession函数覆盖了我编写的运行而没有错误。但是,执行离开该函数后,从Microsoft.Synchronization.CoreInterop.ISyncSession.Start中发生System.Error(据我所知)。
我编写的用于提供IDisposable功能的函数从未被调用过,在EndSession之后,但在我的应用程序的KnowledgeSyncProvider虚拟类可以被处置之前发生了一些事情。
以下是错误信息:
_message:“系统错误。” 堆栈跟踪:在Microsoft.Synchronization.CoreInterop.ISyncSession.Start(CONFLICT_RESOLUTION_POLICY resolutionPolicy,_SYNC_SESSION_STATISTICS& pSyncSessionStatistics) 在Microsoft.Synchronization.KnowledgeSyncOrchestrator.DoOneWaySyncHelper(SyncIdFormatGroup sourceIdFormats,SyncIdFormatGroup destinationIdFormats,KnowledgeSyncProviderConfiguration destinationConfiguration,SyncCallbacks DestinationCallbacks,ISyncProvider sourceProxy,ISyncProvider destinationProxy,ChangeDataAdapter callbackChangeDataAdapter,SyncDataConverter conflictDataConverter,Int32& changesApplied,Int32& changesFailed) 在Microsoft.Synchronization.KnowledgeSyncOrchestrator.DoOneWayKnowledgeSync(SyncDataConverter sourceConverter,SyncDataConverter destinationConverter,SyncProvider sourceProvider,SyncProvider destinationProvider,Int32& changesApplied,Int32& changesFailed) 在Microsoft.Synchronization.KnowledgeSyncOrchestrator.Synchronize() 在Microsoft.Synchronization.SyncOrchestrator.Synchronize() at MyApplication.Library.SynchronizationHelper.SynchronizeProviders()在C:\ My Documents \ Visual Studio 2010 \ Projects \ MyApplication \ MyApplication \ Library \ SynchronizationHelper.cs:第43行 at MyApplication.ViewModels.MainViewModel.SynchronizeDatabases()在C:\ My Documents \ Visual Studio 2010 \ Projects \ MyApplication \ MyApplication \ ViewModels \ MainViewModel.cs:第46行
我已启用跟踪信息,但在这种情况下似乎没有提供任何有用的信息。
有人可以提出一个建议,告诉我如何找出导致此错误的原因吗?
提前感谢您提供的任何帮助。
以下是处理同步的代码:
public void SynchronizeProviders()
{ CeDatabase localDb = new CeDatabase(); localDb.Location = Directory.GetCurrentDirectory()+“\ Data \ SYNCTESTING5.sdf”; RelationalSyncProvider localProvider = ConfigureCeSyncProvider(localDb.Connection); MyAppKnowledgeSyncProvider srcProvider = new MyAppKnowledgeSyncProvider(); localProvider.MemoryDataCacheSize = 5000; localProvider.BatchingDirectory =“c:\ batchingdir”; srcProvider.BatchingDirectory =“c:\ batchingdir”;
SyncOrchestrator orchestrator = new SyncOrchestrator();
orchestrator.LocalProvider = localProvider;
orchestrator.RemoteProvider = srcProvider;
orchestrator.Direction = SyncDirectionOrder.UploadAndDownload;
CheckIfProviderNeedsSchema(localProvider as SqlCeSyncProvider, srcProvider);
SyncOperationStatistics stats = orchestrator.Synchronize();
}
这是用于创建srcProvider的KnowledgeSyncProviderClass:
class MyAppKnowledgeSyncProvider : KnowledgeSyncProvider, IDisposable
{
protected MyAppSqlSync.IMyAppSqlSync proxy;
protected SyncIdFormatGroup idFormatGroup;
protected DirectoryInfo localBatchingDirectory;
protected bool disposed = false;
private string batchingDirectory = Environment.ExpandEnvironmentVariables("%TEMP%");
public string BatchingDirectory
{
get { return batchingDirectory; }
set
{
if (string.IsNullOrEmpty(value))
{
throw new ArgumentException("value cannot be null or empty");
}
try
{
Uri uri = new Uri(value);
if (!uri.IsFile || uri.IsUnc)
{
throw new ArgumentException("value must be a local directory");
}
batchingDirectory = value;
}
catch (Exception e)
{
throw new ArgumentException("Invalid batching directory.", e);
}
}
}
public MyAppKnowledgeSyncProvider()
{
this.proxy = new MyAppSqlSync.MyAppSqlSyncClient();
this.proxy.Initialize();
}
public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext)
{
this.proxy.BeginSession(position);
}
public DbSyncScopeDescription GetScopeDescription()
{
return this.proxy.GetScopeDescription();
}
public override void EndSession(SyncSessionContext syncSessionContext)
{
this.proxy.EndSession();
if (this.localBatchingDirectory != null)
{
this.localBatchingDirectory.Refresh();
if (this.localBatchingDirectory.Exists)
{
this.localBatchingDirectory.Delete(true);
}
}
}
public override ChangeBatch GetChangeBatch(uint batchSize, SyncKnowledge destinationKnowledge, out object changeDataRetriever)
{
MyAppSqlSync.GetChangesParameters changesWrapper = proxy.GetChanges(batchSize, destinationKnowledge);
changeDataRetriever = changesWrapper.DataRetriever;
DbSyncContext context = changeDataRetriever as DbSyncContext;
if (context != null && context.IsDataBatched)
{
if (this.localBatchingDirectory == null)
{
string remotePeerId = context.MadeWithKnowledge.ReplicaId.ToString();
string sessionDir = Path.Combine(this.batchingDirectory, "MyAppSync_" + remotePeerId);
this.localBatchingDirectory = new DirectoryInfo(sessionDir);
if (!this.localBatchingDirectory.Exists)
{
this.localBatchingDirectory.Create();
}
}
string localFileName = Path.Combine(this.localBatchingDirectory.FullName, context.BatchFileName);
FileInfo localFileInfo = new FileInfo(localFileName);
if (!localFileInfo.Exists)
{
byte[] remoteFileContents = this.proxy.DownloadBatchFile(context.BatchFileName);
using (FileStream localFileStream = new FileStream(localFileName, FileMode.Create, FileAccess.Write))
{
localFileStream.Write(remoteFileContents, 0, remoteFileContents.Length);
}
}
context.BatchFileName = localFileName;
}
return changesWrapper.ChangeBatch;
}
public override FullEnumerationChangeBatch GetFullEnumerationChangeBatch(uint batchSize, SyncId lowerEnumerationBound, SyncKnowledge knowledgeForDataRetrieval, out object changeDataRetriever)
{
throw new NotImplementedException();
}
public override void GetSyncBatchParameters(out uint batchSize, out SyncKnowledge knowledge)
{
MyAppSqlSync.SyncBatchParameters wrapper = proxy.GetKnowledge();
batchSize = wrapper.BatchSize;
knowledge = wrapper.DestinationKnowledge;
}
public override SyncIdFormatGroup IdFormats
{
get
{
if (idFormatGroup == null)
{
idFormatGroup = new SyncIdFormatGroup();
idFormatGroup.ChangeUnitIdFormat.IsVariableLength = false;
idFormatGroup.ChangeUnitIdFormat.Length = 1;
idFormatGroup.ReplicaIdFormat.IsVariableLength = false;
idFormatGroup.ReplicaIdFormat.Length = 16;
idFormatGroup.ItemIdFormat.IsVariableLength = true;
idFormatGroup.ItemIdFormat.Length = 10 * 1024;
}
return idFormatGroup;
}
}
public override void ProcessChangeBatch(ConflictResolutionPolicy resolutionPolicy, ChangeBatch sourceChanges, object changeDataRetriever, SyncCallbacks syncCallbacks, SyncSessionStatistics sessionStatistics)
{
DbSyncContext context = changeDataRetriever as DbSyncContext;
if (context != null && context.IsDataBatched)
{
string fileName = new FileInfo(context.BatchFileName).Name;
string peerId = context.MadeWithKnowledge.ReplicaId.ToString();
if (!this.proxy.HasUploadedBatchFile(fileName, peerId))
{
FileStream stream = new FileStream(context.BatchFileName, FileMode.Open, FileAccess.Read);
byte[] contents = new byte[stream.Length];
using (stream)
{
stream.Read(contents, 0, contents.Length);
}
this.proxy.UploadBatchFile(fileName, contents, peerId);
}
context.BatchFileName = fileName;
}
SyncSessionStatistics stats = this.proxy.ApplyChanges(resolutionPolicy, sourceChanges, changeDataRetriever);
sessionStatistics.ChangesApplied += stats.ChangesApplied;
sessionStatistics.ChangesFailed += stats.ChangesFailed;
}
public override void ProcessFullEnumerationChangeBatch(ConflictResolutionPolicy resolutionPolicy, FullEnumerationChangeBatch sourceChanges, object changeDataRetriever, SyncCallbacks syncCallbacks, SyncSessionStatistics sessionStatistics)
{
throw new NotImplementedException();
}
~MyAppKnowledgeSyncProvider()
{
Dispose(false);
}
#region IDisposable Members
public virtual void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
if (this.proxy != null)
{
CloseProxy();
}
}
disposed = true;
}
}
public virtual void CloseProxy()
{
if (this.proxy != null)
{
this.proxy.Cleanup();
ICommunicationObject channel = proxy as ICommunicationObject;
if (channel != null)
{
try
{
channel.Close();
}
catch (TimeoutException)
{
channel.Abort();
}
catch (CommunicationException)
{
channel.Abort();
}
}
this.proxy = null;
}
}
#endregion
}
答案 0 :(得分:0)
奇怪的是,它刚刚开始运作。
我在Visual Studio 2010中收到一条通知,我应该“更新组件”或“安装组件”。它安装了一些Web组件。
现在,我的代码运行没有错误。
虽然我很高兴能够克服这个错误,但我却以一种非常不满意的方式过去了。
好。我会拿走我能得到的东西。