SqlSyncProvider is not interoperable with other Sync Framework Components RRS feed

  • Question

  • This is really only a pseudo-question and more of a discussion, but ultimately I am asking WHY? Why is this so broken Sync Framework Team??

    Here is my very basic scenario: I have a SQL server database provisioned for sync and using Sync Framework 2.1. I have a webservice sitting on top of the database that I want to expose an Atom feed of the database changes. I head over and take a look at: Selecting the Appropriate Sync Framework Components on msdn. From the first picture on the page, it seems pretty obvious to me: slap a FeedProducer on top of a SqlSyncProvider, and Presto! - instant Atom feed of database changes... Not so much.

    Let's dig a little deeper. First off the FeedProducer (and FeedConsumer) both require data converters to convert the incoming data to the appropriate feed xml. OK fair enough, although there is no help for generating correct RSS or Atom xml, that's left entirely to you. Seems like that would have been pretty easy to bake into the Sync Framework. But we'll let that slide for now, because it gets oh so much worse.

    Here's a little background about how the FeedProducer works (the FeedConsumer works the exact same way in reverse). To create a FeedProducer you pass it a KnowledgeSyncProvider in its constructor, along with a couple of converters to help it convert data to feed xml and SyncIds to feed ids. The FeedProducer then internally creates a sync session between the sync provider you passed in (in my case the SqlSyncProvider) and a FeedSyncProvider. The sync session is run: We get a ChangeBatch from the SqlSyncProvider, pass it to the FeedSyncProvider to process the changes, which the FeedSyncProvider does by spitting out your RSS or Atom feed, using your data converters during the process. Seems simple enough right? Wrong!

    Here's the problem: The SqlSyncProvider doesn't play nice. In fact it doesn't play at all. Let's take a closer look at KnowledgeSyncProvider.GetChangeBatch. Here's the signature:

    public ChangeBatch GetChangeBatch(uint batchSize, 
         SyncKnowledge destinationKnowledge, 
         out object changeDataRetriever)

    Typically, (and from all the documentation I've read, all the examples I've seen, and clearly what the FeedSyncProvider is expecting), a KnowledgeSyncProvider is expected to generate a ChangeBatch object with all of the appropriate ChangeItems in it, and should return an object that implements the IChangeDataRetriever interface for the out changeDataRetriever parameter. These parameters will then passed to the other SyncProvider in the sync session to it's ProcessChangeBatch method:

    public void ProcessChangeBatch(ConflictResolutionPolicy resolutionPolicy, 
        ChangeBatch sourceChanges,
        object changeDataRetriever, 
        SyncCallbacks syncCallbacks,
        SyncSessionStatistics sessionStatistics)

    This makes sense right? Now the other SyncProvider can process the changes in the ChangeBatch by enumerating the ChangeItems, and calling the IChangeDataRetriever interface to get the actual data for the change. 

    What does the SqlSyncProvider do? Not that! It's implementation of GetChangeBatch actually always returns an empty ChangeBatch (with no ChangeItems in it). And the changeDataRetriever parameter is set to a DbSyncContext object. But does that implement the IChangeDataRetriever interface? Nope! It just contains a DataSet with all the changes in it. And how about the SqlSyncProvider's implementation of ProcessChangeBatch? Turns out it completely ignores the ChangeBatch parameter, assumes the changeDataRetriever parameter is a DbSyncContext, and proceeds to use the DataSet to process the changes.

    So what does all that mean? Basically it means that if you're synchronizing between two SqlSyncProviders, it works great. But try using the SqlSyncProvider in the larger Sync Framework ecosystem... forget about it! And that brings us back to the beginning - why? Why implement the SqlSyncProvider so that it can only be used with another SqlSyncProvider? Why show in the documentation that the SqlSyncProvider is a friendly-neighborhood KnowledgeSyncProvider, when it's really playing by it's own rules? 

    Thursday, March 17, 2011 7:03 PM

All replies