<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>8bit Blog &#187; Synchronization Framework</title>
	<atom:link href="http://www.8bit.rs/blog/category/microsoft-net/synchronization-framework/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.8bit.rs/blog</link>
	<description></description>
	<lastBuildDate>Mon, 07 May 2012 14:42:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>An update to “Remote File Sync using WCF and MSF”</title>
		<link>http://www.8bit.rs/blog/2010/04/an-update-to-remote-file-sync-using-wcf-and-msf/</link>
		<comments>http://www.8bit.rs/blog/2010/04/an-update-to-remote-file-sync-using-wcf-and-msf/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 22:28:49 +0000</pubDate>
		<dc:creator>bdrajer</dc:creator>
				<category><![CDATA[Microsoft .Net]]></category>
		<category><![CDATA[Synchronization Framework]]></category>

		<guid isPermaLink="false">http://www.8bit.rs/blog/index.php/2010/11/an-update-to-remote-file-sync-using-wcf-and-msf/</guid>
		<description><![CDATA[This is a follow-up to Bryant Likes’ post where he gave a prototype solution for file synchronization over WCF. I converted the code to Microsoft Sync Framework 2.0 so now it compiles and seems to run well enough. But you have to keep in mind that it isn’t a complete example (it wasn’t that in [...]]]></description>
			<content:encoded><![CDATA[<p>This is a follow-up to <a href="http://bryantlikes.com/archive/2008/01/03/remote-file-sync-using-wcf-and-msf.aspx" target="_blank">Bryant Likes’ post</a> where he gave a prototype solution for file synchronization over WCF. I converted the code to Microsoft Sync Framework 2.0 so now it compiles and seems to run well enough. But you have to keep in mind that it isn’t a complete example (it wasn’t that in the original code either): it only does upload sync, it doesn’t have any conflict resolution logic etc. It is my opinion that this is not really worth pursuing any further, because one would need to develop two complete custom providers &#8211; and all that (just for copying files?) when there’s an existing FileSyncProvider in the framework which knows how to cooperate with other providers so it should be able to communicate over WCF… On the other hand, if you do pull the heroic act of completing this code, please let me know because I’m (obviously) very interested in it. I tried to keep the modified code as close to the original as possible so that a simple diff (e.g. WinMerge) can show what I’ve done, because I’m not sure I got it all right (as I’m afraid Bryant wasn’t, too).</p>
<p>Here’s the complete solution: <a href="http://www.8bit.rs/download/samples/RemoteSync converted to MSF 2.0.zip">http://www.8bit.rs/download/samples/RemoteSync converted to MSF 2.0.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.8bit.rs/blog/2010/04/an-update-to-remote-file-sync-using-wcf-and-msf/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Replicating self-referencing tables and circular foreign keys with Microsoft Sync Framework</title>
		<link>http://www.8bit.rs/blog/2009/12/replicating-self-referencing-tables-and-circular-foreign-keys-with-microsoft-sync-framework/</link>
		<comments>http://www.8bit.rs/blog/2009/12/replicating-self-referencing-tables-and-circular-foreign-keys-with-microsoft-sync-framework/#comments</comments>
		<pubDate>Fri, 11 Dec 2009 10:55:22 +0000</pubDate>
		<dc:creator>bdrajer</dc:creator>
				<category><![CDATA[Synchronization Framework]]></category>

		<guid isPermaLink="false">http://www.8bit.rs/blog/index.php/2009/12/replicating-self-referencing-tables-and-circular-foreign-keys-with-microsoft-sync-framework/</guid>
		<description><![CDATA[Self-referencing tables – or, at least circular foreign key references between tables – are probably a common thing in all but the simplest database designs. Yet Microsoft Sync Framework doesn’t have a clear strategy on how to replicate such data. I found various suggestions on the net: order rows so that the parent records come [...]]]></description>
			<content:encoded><![CDATA[<p>Self-referencing tables – or, at least circular foreign key references between tables – are probably a common thing in all but the simplest database designs. Yet Microsoft Sync Framework doesn’t have a clear strategy on how to replicate such data. I found various suggestions on the net: order rows so that the parent records come before children – this is usable for self-referencing tables (although not endorsed by Microsoft because the framework doesn’t guarantee it will respect this order), but not nearly good enough for circular references – if you have two rows in two tables pointing at each other, ordering them cannot solve the problem. On an MSDN forum there was a <a href="http://social.microsoft.com/Forums/en-US/uklaunch2007ado.net/thread/4386b809-17a2-41ef-b3dc-6d64d1ef2f26" target="_blank">suggestion</a> to temporarily disable foreign key constraints: this I cannot take seriously because it opens my database to corruption, all it takes is one faulty write while the constraint is down and I have invalid data in the database (unless I lock the tables before synchronization, and I’m not sure how to do this from within the Sync Framework).</p>
<p>So, when all else fails, you have to sit and think: what would be the general principle for solving this, Sync Framework notwithstanding? Exactly &#8211; do it in two passes. The problem is present only when inserting rows, if the row contains a reference to another row that wasn’t yet created, we get a foreign key violation… Our strategy could be to insert all rows without setting foreign key field values, then do another pass to just connect the foreign keys. If we do this after <em>all</em> tables have finished their first pass (inserts, updates, deletes and all), we also support the circular references because required rows are present in all tables.</p>
<p>Ok, that was fairly easy to figure out (not much harder to implement either, but more on that later). We have another issue here that is not so obvious, deleting the rows… There may be other rows referencing the one we are deleting that haven’t yet been replicated. Since the Sync Framework applies the deletes first, we can be fairly certain that the referencing rows are yet to be replicated &#8211; they will either be deleted or updated to reference something else. So we can put a null value in all fields that reference our row. (Note that this will probably mark the other rows as modified and cause them to be replicated back – this is an issue I won’t go into in this post, but I’m quite certain there needs to be a global mechanism for disabling change tracking while we’re writing replicated data. I currently use a temporary “secret handshake” solution: I send a special value &#8211; the birth date of Humphrey Bogart &#8211; in the row’s creation/last update date fields that disables the change tracking trigger).</p>
<p>Ok, on to the code. I won’t give you a working example here, just sample lines with comments. You’ve probably figured out by now that it will be necessary to write SQL commands for the sync adapter by hand. I don’t know about you, but I’m no longer surprised by this: many of the tools and components we get in the .Net framework packages solve just the simplest problems and provide nice demos – if you need anything clever, you code it by hand. My solution was to create my own designer/code generator, and now I’m free to support any feature I need (also, I am able to do it <em>much</em> faster than Microsoft, for whatever reason: it took me a couple of days to add this feature… It may be that I’m standing on the shoulders of giants, but the giants could really have spared a couple of days to do this themselves).</p>
<p>For simplicity, I’ll show how to replicate a circular reference: there’s an Item table that has an ID, a Name, and a ParentID, referencing itself. For replication, I split the table into two SyncAdapters: Item, that inserts only ID and Name and has a special delete command to eliminate foreign references beforehand, and Item2ndPass, which has only the insert command – but the only thing insert command does is wiring up of ParentID’s, it does not insert anything. I’ve deleted all the usual command creation and parameter addition code, the point is only to show the SQL’s, since they hold the key to the solution.</p>
<pre>[Serializable]
public partial class ItemSyncAdapter : Microsoft.Synchronization.Data.Server.SyncAdapter
{
	partial void OnInitialized();

	public ItemSyncAdapter()
	{
		this.InitializeCommands();
		this.InitializeAdapterProperties();
		this.OnInitialized();
	}

	private void InitializeCommands()
	{
		// InsertCommand
		// 1899-12-25 00:00:00.000 is a 'Humphrey Bogart' special value telling
		// the change tracking trigger to skip this row
		this.InsertCommand.CommandText =  @"SET IDENTITY_INSERT Item ON
INSERT INTO Item ([ID], [Name], [CreatedDate], [LastUpdatedDate]) VALUES (@ID, @Name,
@sync_last_received_anchor, '1899-12-25 00:00:00.000') SET @sync_row_count = @@rowcount
SET IDENTITY_INSERT Item OFF";

		// UpdateCommand
		this.UpdateCommand.CommandText = @"UPDATE Item SET [Name] = @Name,
CreatedDate='1899-12-25 00:00:00.000', LastUpdatedDate=@sync_last_received_anchor WHERE
([ID] = @ID) AND (@sync_force_write = 1 OR ([LastUpdatedDate] IS NULL OR [LastUpdatedDate]
&lt;= @sync_last_received_anchor)) SET @sync_row_count = @@rowcount";		

		// DeleteCommand
		this.DeleteCommand.CommandText = @"UPDATE Item SET [ParentID] = NULL
WHERE [ParentID] = @ID DELETE FROM Item WHERE ([ID] = @ID) AND (@sync_force_write = 1 OR
([LastUpdatedDate] &lt;= @sync_last_received_anchor OR [LastUpdatedDate] IS NULL))
SET @sync_row_count = @@rowcount";

		// SelectConflictUpdatedRowsCommand, SelectConflictDeletedRowsCommand
		// skipped because they are not relevant

		// SelectIncrementalInsertsCommand
		this.SelectIncrementalInsertsCommand.CommandText = @"SELECT  [ID],
[ParentID], [CreatedDate], [LastUpdatedDate] FROM Item WHERE ([CreatedDate] &gt;
@sync_last_received_anchor AND [CreatedDate] &lt;= @sync_new_received_anchor)";

		// SelectIncrementalUpdatesCommand
		this.SelectIncrementalUpdatesCommand.CommandText = @"SELECT  [ID],
[ParentID], [CreatedDate], [LastUpdatedDate] FROM Item WHERE ([LastUpdatedDate] &gt;
@sync_last_received_anchor AND [LastUpdatedDate] &lt;= @sync_new_received_anchor AND
[CreatedDate] &lt;= @sync_last_received_anchor)";

		// SelectIncrementalDeletesCommand
		this.SelectIncrementalDeletesCommand.CommandText = @"SELECT FirstID
AS ID FROM sys_ReplicationTombstone WHERE NameOfTable = 'Item' AND DeletionDate &gt;
@sync_last_received_anchor AND DeletionDate &lt;= @sync_new_received_anchor";
	}

	private void InitializeAdapterProperties()
	{
		this.TableName = "Item";
	}

} // end ItemSyncAdapter
[Serializable]
public partial class Item2ndPassSyncAdapter : Microsoft.Synchronization.Data.Server.SyncAdapter
{
	partial void OnInitialized();

	public Item2ndPassSyncAdapter()
	{
		this.InitializeCommands();
		this.InitializeAdapterProperties();
		this.OnInitialized();
	}

	private void InitializeCommands()
	{
		// InsertCommand
		this.InsertCommand.CommandText =  @"UPDATE Item SET [ParentID] = @ParentID,
CreatedDate='1899-12-25 00:00:00.000', LastUpdatedDate=@sync_last_received_anchor WHERE ([ID] =
@ID) AND (@sync_force_write = 1 OR ([LastUpdatedDate] IS NULL OR [LastUpdatedDate] &lt;=
@sync_last_received_anchor)) SET @sync_row_count = @@rowcount";

		// SelectIncrementalInsertsCommand
		this.SelectIncrementalInsertsCommand.CommandText = @"SELECT  [ID],
[ParentID] FROM Item WHERE ([CreatedDate] &gt; @sync_last_received_anchor AND [CreatedDate] &lt;=
@sync_new_received_anchor)";

	}

	private void InitializeAdapterProperties()
	{
		this.TableName = "Item2ndPass";
	}

} // end Item2ndPassSyncAdapter</pre>
<p>In this case, it would be enough to setup the second-pass sync adapter to be executed after the first one. For circular references, I put all second-pass adapters at the end, after all first-pass adapters. Notice that the commands for selecting incremental inserts and updates read all columns &#8211; this is probably suboptimal because some fields will not be used, but it&#8217;s much more convenient to have all field values handy than to rework the whole code generator template for each minor adjustment.</p>
<p>UPDATE (24.11.2010): I’ve added a source file with an illustration for this solution. I haven’t tested it (although it does compile and may well work) but it could be useful in showing the overall picture. It was created by extracting one generated sync adapter from my application, hacking away most of our specific code and then making it compile.</p>
<p><a href="http://www.8bit.rs/download/samples/ItemSyncAgentSample.cs">http://www.8bit.rs/download/samples/ItemSyncAgentSample.cs</a></p>
<p>Note that the file contains a couple of things that stray away from standard implementation, like using one table for all tombstone records, using the sample sql express client sync provider etc. Just ignore these. One thing, though, may be of interest (I may even do a blog post about it one day): the insert command knows how to restore autoincrement ID after replication, so that different autoincrement ranges can exist in different replicated databases (no GUIDs are used for primary keys) and identity insert is possible. This is necessary because SQL server automatically sets the current autoincrement seed to the largest value inserted in the autoincrement column. Keep in mind that this (as well as the whole class, for that matter) may not be the best way to do things – but I’ve been using it for some time now and haven’t had any problems.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.8bit.rs/blog/2009/12/replicating-self-referencing-tables-and-circular-foreign-keys-with-microsoft-sync-framework/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Sync Framework 2 CTP2 – no SqlExpressClientSyncProvider yet</title>
		<link>http://www.8bit.rs/blog/2009/09/sync-framework-2-ctp2-no-sqlexpressclientsyncprovider-yet/</link>
		<comments>http://www.8bit.rs/blog/2009/09/sync-framework-2-ctp2-no-sqlexpressclientsyncprovider-yet/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 13:54:38 +0000</pubDate>
		<dc:creator>bdrajer</dc:creator>
				<category><![CDATA[Microsoft .Net]]></category>
		<category><![CDATA[Synchronization Framework]]></category>

		<guid isPermaLink="false">http://www.8bit.rs/blog/index.php/2009/09/sync-framework-2-ctp2-no-sqlexpressclientsyncprovider-yet/</guid>
		<description><![CDATA[Ok, I’ve finally gotten around to installing the CTP2 of the Sync framework. Let&#8217;s see what new and interesting stuff I got with it: 1. A headache. 2. Erm&#8230; anything else? All witticism aside, a lot of details have probably changed, but the main gripe I had still stands: there is no support for hub-and-spoke [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, I’ve finally gotten around to installing the CTP2 of the Sync framework. Let&#8217;s see what new and interesting stuff I got with it:</p>
<p>1. A headache.   <br />2. Erm&#8230; anything else? </p>
<p>All witticism aside, a lot of details have probably changed, but the main gripe I had still stands: there is no support for hub-and-spoke replication between two SQL servers etc. (Oh, and the designer is still unusable… <em>Two </em>gripes).</p>
<p>As for the first thing, I hoped I was finally going to get rid of my SqlExpressClientSyncProvider debugged demo but no such luck. It turns out that nothing of the sort is (yet?) included in the sync framework. Judging by <a href="http://social.microsoft.com/Forums/en-US/uklaunch2007ado.net/thread/eeede8d2-4cce-4398-b12e-1abd72cbc81d" target="_blank">a forum post</a>, v2 is soon due to be released, but any questions regarding the Sql Express provider are met with a dead silence. It doesn’t seem it will be included this time (9200 downloads of the SqlExpressClientSyncProvider demo are obviously not significant for these guys). You almost literally have to read between the lines: regarding information about this CTP, there was a very sparse announcement, and a somewhat misleading one at that (and since this is the only information you get, any ambiguity can lead you in the wrong direction).</p>
<p>The CTP2 release announcement said: </p>
<p><em># New database providers (SqlSyncProvider and SqlCeSyncProvider)      <br />Enable hub-and-spoke and peer-to-peer synchronization for SQL Server, SQL Server Express, and SQL Server Compact. </em></p>
<p>So, does SqlSyncProvider work in hub-and-spoke scenario? I thought yes. How would you interpret the above sentence?</p>
<p>The truth is that SqlSyncProvider cannot be used as local sync provider in a SyncAgent (that is, in a hub-and-spoke scenario as I know it) because it is not derived from ClientSyncProvider. The SyncAgent explicitly denies it &#8211; and throws a very un-useful exception that says, essentially “ClientSyncProvider”… Translated, this means: “use the Reflector to see what has happened”, which I did. The code in the SyncAgent looks like this:</p>
<pre>public SyncProvider LocalProvider
{
    get
    {
        return this._localProvider;
    }
    set
    {
        ClientSyncProvider provider = value as ClientSyncProvider;
        if ((value != null) &amp;&amp; (provider == null))
        {
            throw new InvalidCastException(typeof(ClientSyncProvider).ToString());
        }
        this._localProvider = provider;
    }
}</pre>
<p>(Someone was too lazy to write a meaningful error message… How much effort does it take? I know I wouldn’t tolerate this kind of behavior in my company.)</p>
<p>So there’s no chance for it to work (or I’m somehow using an old version of the SyncAgent). Is there any other way to do a hub-and-spoke sync, without a SyncAgent? I don’t know of it. But the docs for the CTP2 say:</p>
<p><em>SqlSyncProvider and SqlCeSyncProvider can be used for client-server, peer-to-peer, and mixed topologies, whereas DbServerSyncProvider and SqlCeClientSyncProvider are appropriate only for client-server topologies.</em></p>
<p>I thought that client-server is the same as hub-and-spoke, now I’m not so sure… At the end, after hours spent researching, I still don&#8217;t know what to think.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.8bit.rs/blog/2009/09/sync-framework-2-ctp2-no-sqlexpressclientsyncprovider-yet/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Debugging SQL Express Client Sync Provider</title>
		<link>http://www.8bit.rs/blog/2009/05/debugging-sql-express-client-sync-provider/</link>
		<comments>http://www.8bit.rs/blog/2009/05/debugging-sql-express-client-sync-provider/#comments</comments>
		<pubDate>Tue, 05 May 2009 12:01:00 +0000</pubDate>
		<dc:creator>bdrajer</dc:creator>
				<category><![CDATA[Microsoft .Net]]></category>
		<category><![CDATA[Synchronization Framework]]></category>

		<guid isPermaLink="false">http://www.8bit.rs/blog/?p=23</guid>
		<description><![CDATA[How to finally get the SQL Express Client Sync Provider to work correctly? It’s been almost a year since it was released, and still it has documented bugs. One was detected by Microsoft more than a month after release and documented on the forum, but the fix was never included in the released version. We [...]]]></description>
			<content:encoded><![CDATA[<p>How to finally get the SQL Express Client Sync Provider to work correctly? It’s been almost a year since it was <a href="http://blogs.msdn.com/mahjayar/archive/2008/06/24/announcing-availability-of-a-new-sync-sample-sql-express-client-synchronization-using-sync-services-for-ado-net.aspx" target="_blank">released</a>, and still it has documented bugs. One was detected by Microsoft more than a month after release and documented <a href="http://social.msdn.microsoft.com/Forums/en-US/uklaunch2007ado.net/thread/9e65722a-cdb7-46e2-8a44-c6b466ed873b" target="_blank">on the forum</a>, but the fix was never included in the released version. We could analyze this kind of shameless negligence in the context of Microsoft&#8217;s overall quality policies, but it’s a broad (and also well documented) topic, so we’ll leave it at that. It wouldn’t be such a problem if there were no people interested in using it, but there are, very much so. So, what else is there to do than to try to fix what we can ourselves…</p>
<p>You can find the source for the class <a href="/download/samples/SqlExpressClientSyncProvider.cs" target="_blank">here</a>. To use it, you may also want to download (if you don’t already have it) the original <a href="http://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=sync&amp;ReleaseId=1200" target="_blank">sql express provider source</a> which has the solution and project files which I didn’t include. (UPDATE: the original source seems to be removed from the MSDN site, and my code was updated &#8211; see the comments for this post to download the latest version).</p>
<p>The first (and solved, albeit only on the forum) problem was that the provider was reversing the sync direction. This happens because the client provider basically simulates client behavior by internally using a <em>server</em> provider. In hub-and-spoke replication, the distinction between client and server is important since only the client databases keep track of synchronization anchors (that is, remember what was replicated and when).</p>
<p>I also incorporated support for datetime anchors I proposed in the mentioned <a href="http://social.msdn.microsoft.com/Forums/en-US/uklaunch2007ado.net/thread/9e65722a-cdb7-46e2-8a44-c6b466ed873b" target="_blank">forum post</a>, which wasn’t present in the original source.</p>
<p>But that is not all that’s wrong with the provider: it seems that it also swaps client and server anchors, and <em>that</em> is a very serious blunder because it’s very hard to detect. It effectively uses client time/timestamps to detect changes on the server and vice versa. I tested it using datetime anchors, and this is the most dangerous situation because if the server clocks aren’t perfectly synchronized, data can be lost. (It might behave differently with timestamps, but it doubt it).</p>
<p>The obvious solution for anchors is to also swap them before and after running synchronization. This can be done by modifying the ApplyChanges method like this:</p>
<pre>foreach (SyncTableMetadata metaTable in groupMetadata.TablesMetadata)
{
    SyncAnchor temp = metaTable.LastReceivedAnchor;
    metaTable.LastReceivedAnchor = metaTable.LastSentAnchor;
    metaTable.LastSentAnchor = temp;
} 

// this is the original line
SyncContext syncContext = _dbSyncProvider.ApplyChanges(groupMetadata, dataSet, syncSession); 

foreach (SyncTableMetadata metaTable in groupMetadata.TablesMetadata)
{
    SyncAnchor temp = metaTable.LastReceivedAnchor;
    metaTable.LastReceivedAnchor = metaTable.LastSentAnchor;
    metaTable.LastSentAnchor = temp;
}</pre>
<p>This seems to correct the anchor confusion but for some reason the @sync_new_received_anchor parameter still receives an invalid value in the update/insert/delete stage, so it shouldn’t be used. The reason for this could be that both the client and server use the same sync metadata and that the server sync provider posing as client probably doesn’t think it is required to leave valid anchor values after it’s finished. I promise to post in the future some more information I gathered poking around the sync framework innards.</p>
<p>Note that this version is by no means fully tested nor without issues, but its basic functionality seems correct. You have to be careful to use @sync_new_anchor only in queries that <em>select</em> changes (either that or modify the provider further to correct this behaviour: I think this can be done by storing and restoring anchors in the metadata during ApplyChanges, but I’m not sure whether this is compatible with the provider internal logic). Another minor issue I found was that the trace log reports both client and server providers as servers.</p>
<p>If you find and/or fix another issue with the provider, please post a comment here so that we can one day have a fully functional provider.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.8bit.rs/blog/2009/05/debugging-sql-express-client-sync-provider/feed/</wfw:commentRss>
		<slash:comments>33</slash:comments>
		</item>
	</channel>
</rss>

