1

我正在编写一个将 Sync Framework v2.1 与 WCF Web 服务结合使用的 n 层应用程序。我的代码基于这个例子:Database-Sync

同步似乎没有问题。但是,当我添加批处理功能时,我得到了一个难以调试的错误。

在解决方案的客户端部分(WPF 应用程序)中,我有一个继承自 KnowledgeSyncProvider 的虚拟类。它还实现了 IDisposable 接口。我使用这个类来调用我编写的 WCF 服务并在那里使用同步功能。当同步代码运行时(调用了 orchestrator.Synchronize()),一切似乎都正常工作,并且我编写的 EndSession 函数覆盖运行没有错误。但是,在执行离开该函数后,Microsoft.Synchronization.CoreInterop.ISyncSession.Start 内部会发生 System.Error(据我所知)。

我为提供 IDisposable 功能而编写的函数从未被调用过,在 EndSession 之后发生了一些事情,但在我的应用程序的 KnowledgeSyncProvider 虚拟类可以被释放之前。

这是错误信息:

_message:“系统错误。” 堆栈跟踪:在 Microsoft.Synchronization.KnowledgeSyncOrchestrator.DoOneWaySyncHelper(SyncIdFormatGroup sourceIdFormats,SyncIdFormatGroup destinationIdFormats,KnowledgeSyncProviderConfiguration 目标位置,SyncChangeCallbacks DestinationCallbacks,IDataSyncProvider 回调目标,目标回调,IDataSyncProvider sourceIdFormats 的 Microsoft.Synchronization.CoreInterop.ISyncSession.Start(CONFLICT_RESOLUTION_POLICY resolutionPolicy,_SYNC_SESSION_STATISTICS& pSyncSessionStatistics) Microsoft.Synchronization.KnowledgeSyncOrchestrator.DoOneWayKnowledgeSync(SyncDataConverter sourceConverter、SyncDataConverter destinationConverter、SyncProvider sourceProvider、

我启用了跟踪信息,但在这种情况下似乎没有提供任何有用的信息。

任何人都可以就我如何找出导致此错误的原因提出建议吗?

提前感谢您提供的任何帮助。

这是处理同步的代码:

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
}
4

1 回答 1

0

奇怪的是,它才刚刚开始工作。

我在 Visual Studio 2010 中收到一条通知,我应该“更新组件”或“安装组件”。它安装了一些 Web 组件。

现在,我的代码运行没有错误。

虽然我很高兴克服了这个错误,但我以一种非常不满意的方式克服了它。

出色地。我会拿走我能得到的。

于 2012-08-07T12:13:29.510 回答