<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Mahjayar's WebLog.</title><link>http://blogs.msdn.com/b/mahjayar/</link><description /><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>New year and new beginings</title><link>http://blogs.msdn.com/b/mahjayar/archive/2011/04/16/new-year-and-new-beginings.aspx</link><pubDate>Sat, 16 Apr 2011 21:21:46 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10154838</guid><dc:creator>mahjayar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/mahjayar/rsscomments.aspx?WeblogPostID=10154838</wfw:commentRss><comments>http://blogs.msdn.com/b/mahjayar/archive/2011/04/16/new-year-and-new-beginings.aspx#comments</comments><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I have recently made the decision to start on a new adventure outside Microsoft. With me moving out of Microsoft, I will no longer have access to manage this blog. For the past couple of years I have been cross posting all my posts on my personal blog at &lt;a href="http://maheshwar.net/blog"&gt;http://maheshwar.net/blog&lt;/a&gt; and moving forward that will be my primary blog. I know this is not a high traffic blog but if you have me on your subscription lists then please change your feeds over to &lt;a href="http://maheshwar.net/Blog/syndication.axd"&gt;http://maheshwar.net/Blog/syndication.axd&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;I will be posting about my new adventures over on my personal blog soon. &lt;/p&gt;
&lt;p&gt;Maheshwar&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10154838" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/personal/">personal</category></item><item><title>Sync Framework 4.0 CTP Refresh Now Available</title><link>http://blogs.msdn.com/b/mahjayar/archive/2010/11/18/sync-framework-4-0-ctp-refresh-now-available.aspx</link><pubDate>Thu, 18 Nov 2010 19:43:45 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10093463</guid><dc:creator>mahjayar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/mahjayar/rsscomments.aspx?WeblogPostID=10093463</wfw:commentRss><comments>http://blogs.msdn.com/b/mahjayar/archive/2010/11/18/sync-framework-4-0-ctp-refresh-now-available.aspx#comments</comments><description>&lt;p&gt;As mentioned in my earlier post the 4.0 CTP refresh is now available. It contains the UI Helper for SyncSvcUtil.exe command line tool in addition to the iPhone sample client for the Lists sample. Please download the bits from &lt;a title="here" href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=afd89099-d589-423c-9762-78096aa95ac2&amp;amp;displaylang=en"&gt;here&lt;/a&gt;. We have also updated the documentation in this refresh which now shows step by step instructions on how to use the UI tool. Documentation can be found &lt;a title="here" href="http://msdn.microsoft.com/en-us/library/gg299051(v=SQL.110).aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Some presentations that talks and shows off the latest CTP is also available.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;PDC 2010 Session&lt;/strong&gt;: To learn more about this release 4.0 in general, take a look at our PDC session recording &amp;quot;&lt;a href="http://player.microsoftpdc.com/Session/28830999-dd97-45c4-9bb4-bb16ba21a6b0"&gt;Building Offline Applications using Sync Framework and SQL Azure&lt;/a&gt;&amp;quot;.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Sql PASS 2010 Session&lt;/strong&gt;: The recording for this talk is not available online but the presentation is available online. Its over &lt;a href="http://cid-1020651b1389d347.office-df.live.com/view.aspx/Public/Building%20offline%20applications%20for%20Windows%20Phone%20and%20other%20devices%20using%20Sync%20Framework.pptx"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10093463" width="1" height="1"&gt;</description></item><item><title>Announcing Sync Framework 4.0 CTP</title><link>http://blogs.msdn.com/b/mahjayar/archive/2010/11/09/announcing-sync-framework-4-0-ctp.aspx</link><pubDate>Wed, 10 Nov 2010 05:29:25 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10088612</guid><dc:creator>mahjayar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/mahjayar/rsscomments.aspx?WeblogPostID=10088612</wfw:commentRss><comments>http://blogs.msdn.com/b/mahjayar/archive/2010/11/09/announcing-sync-framework-4-0-ctp.aspx#comments</comments><description>&lt;p&gt;Back in Mix 10 we showed an &lt;a href="http://blogs.msdn.com/b/mahjayar/archive/2010/03/01/announcing-the-availability-of-the-mix10-session-planner-beta.aspx"&gt;application&lt;/a&gt; built with the intention of extending the Sync Framework to Silverlight platform. This enabled rich apps built on Silverlight for desktop and Windows Phone 7 to participate in a sync topology. At that point we only showed an application built on our early thinking. Since then we have been off trying to package it for public consumption. I am very glad to announce the public availability of the Sync Framework 4.0 CTP which enables users to now build similar applications. With this release we are announcing the Asymmetric Sync toplogy that enables offline application development on any client platform that has capability of persisting data. Up until Sync Fx 2.1 users had to have Windows to be able to use the Sync framework. One of the most common feature requests were to ship the framework for windows devices (CE, embedded and the WM 6.X) platform. With the advent of Windows Phone 7 we took a long hard look at the device/non windows platform support and the asymmetric sync was one such solution we decided to pursue. Asymmetric sync standardizes on a protocol instead of a sync components on clients and moved ALL sync framework components to the server side. This enabled client platforms such as Silverlight (desktop and Windows Phone 7), HTML5, iPhone, Android, RIM and others have the ability to build offline apps synchronizing with a standard sync service. &lt;/p&gt;
&lt;p&gt;Sync Framework 4.0 (yes we skipped 3.0!) CTP is not available. Please visit &lt;a href="http://blogs.msdn.com/b/sync/archive/2010/10/28/announcing-sync-framework-4-0-october-2010-ctp.aspx"&gt;http://blogs.msdn.com/b/sync/archive/2010/10/28/announcing-sync-framework-4-0-october-2010-ctp.aspx&lt;/a&gt;&amp;nbsp;for more information and the scenarios it enables. We are very excitied with this release as this opens the Sync framework to a completely new set of developers and we cant wait to see the interesting scenarios these developers will come up with.&lt;/p&gt;
&lt;p&gt;I am presenting at Sql PASS 2010 tomorrow on Sync Framework 4.0. If you are attending Sql PASS&amp;nbsp;then try to attend &lt;a href="http://sqlpass.eventpoint.com/topic/details/AD300M"&gt;this&lt;/a&gt; session. The session should be available for on demand viewing later and I will update with a direct link to the presentation.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlpass.eventpoint.com/topic/details/AD300M"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10088612" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Framework/">Sync Framework</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/SQL+Azure/">SQL Azure</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Asymmetric+Sync/">Asymmetric Sync</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Framework+4-0/">Sync Framework 4.0</category></item><item><title>Announcing the availability of the MIX10 Session Planner (Beta)</title><link>http://blogs.msdn.com/b/mahjayar/archive/2010/03/01/announcing-the-availability-of-the-mix10-session-planner-beta.aspx</link><pubDate>Mon, 01 Mar 2010 23:49:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9971193</guid><dc:creator>mahjayar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/mahjayar/rsscomments.aspx?WeblogPostID=9971193</wfw:commentRss><comments>http://blogs.msdn.com/b/mahjayar/archive/2010/03/01/announcing-the-availability-of-the-mix10-session-planner-beta.aspx#comments</comments><description>&lt;P&gt;Sorry for the radio silence the past couple of months. We have been working on our the next version of Microsoft Sync Framework and as part of that we decided to do a little preview of our work at MIX10. For starters we have made the MIX10 Session Planner (Beta) public that provides an offline cache/Synchronization of the MIX sessions data in Silverlight. The synchronization brains for the app is built on top of our early Sync 3.0 code base and provides a glimpse of the direction we are heading towards. We will have lots more to discuss at MIX on the architecture of the service. For the time being visit &lt;A href="http://live.visitmix.com/News/MIX10-Session-Planner"&gt;http://live.visitmix.com/News/MIX10-Session-Planner&lt;/A&gt;&amp;nbsp;to get started on using the offline cache experience (note LiveID sign in required).&lt;/P&gt;
&lt;P&gt;PS: If the synchronization space is something you are interested in and would like to join our team we are still &lt;A href="http://blogs.msdn.com/mahjayar/archive/2010/01/14/software-engineer-in-test-opportunities-available-in-the-microsoft-sync-framework-team.aspx" mce_href="http://blogs.msdn.com/mahjayar/archive/2010/01/14/software-engineer-in-test-opportunities-available-in-the-microsoft-sync-framework-team.aspx"&gt;hiring&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Maheshwar Jayaraman&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9971193" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Silverlight/">Silverlight</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Framework/">Sync Framework</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Services+for+ADO-NET/">Sync Services for ADO.NET</category></item><item><title>Software Engineer In Test Opportunities Available In The Microsoft Sync Framework team</title><link>http://blogs.msdn.com/b/mahjayar/archive/2010/01/14/software-engineer-in-test-opportunities-available-in-the-microsoft-sync-framework-team.aspx</link><pubDate>Fri, 15 Jan 2010 00:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9948728</guid><dc:creator>mahjayar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/mahjayar/rsscomments.aspx?WeblogPostID=9948728</wfw:commentRss><comments>http://blogs.msdn.com/b/mahjayar/archive/2010/01/14/software-engineer-in-test-opportunities-available-in-the-microsoft-sync-framework-team.aspx#comments</comments><description>&lt;P&gt;If you are interested in the data synchronization space then we have opportunties available on the Microsoft Sync Framework team. Refer &lt;A href="https://careers.microsoft.com/JobDetails.aspx?ss=&amp;amp;pg=0&amp;amp;so=&amp;amp;rw=1&amp;amp;jid=11145&amp;amp;jlang=EN"&gt;https://careers.microsoft.com/JobDetails.aspx?ss=&amp;amp;pg=0&amp;amp;so=&amp;amp;rw=1&amp;amp;jid=11145&amp;amp;jlang=EN&lt;/A&gt;. You can apply directly on Microsoft career site or use the contact link in this blog to send me your resume. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9948728" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Framework/">Sync Framework</category></item><item><title>SQL Azure Data Sync – Moving Schema from Compact Database to SQL Azure</title><link>http://blogs.msdn.com/b/mahjayar/archive/2009/11/18/sql-azure-data-sync-moving-schema-from-compact-database-to-sql-azure.aspx</link><pubDate>Thu, 19 Nov 2009 01:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9924973</guid><dc:creator>mahjayar</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/mahjayar/rsscomments.aspx?WeblogPostID=9924973</wfw:commentRss><comments>http://blogs.msdn.com/b/mahjayar/archive/2009/11/18/sql-azure-data-sync-moving-schema-from-compact-database-to-sql-azure.aspx#comments</comments><description>&lt;P align=justify&gt;&lt;STRONG&gt;Update 12/11&lt;/STRONG&gt;:&amp;nbsp;Fixing a typo in the code as pointed by the commenter.&lt;/P&gt;
&lt;P align=justify&gt;With yesterdays announcement of the Microsoft Sync Framework Power Pack for SQL Azure, we have had questions on how to move sync schema from SQL Compact database up to SQL Azure. The power pack only comes with tools to automate the sync schema setup from SQL Server to SQL Azure (via the SQL Azure Data Sync Tool) and taking SQL Azure data offline to a new compact database (via the VS Add New Item template). There is no UI tool to go from Compact to SQL Azure or even SQL Azure to SQL Server. &lt;/P&gt;
&lt;P align=justify&gt;Just wanted to point out that its quite simple to achieve the above two non UI supported scenarios via code. Attached is the simple code that shows how to move sync schema from Compact to SQL Azure.&lt;/P&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Collections.Generic;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Linq;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Text;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Data.SqlServerCe;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; Microsoft.Synchronization.Data;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; Microsoft.Synchronization.Data.SqlServerCe;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; Microsoft.Synchronization.Data.SqlAzure;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Data.SqlClient;
&lt;SPAN class=kwrd&gt;namespace&lt;/SPAN&gt; ConsoleApplication1
{
    &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; Program
    {
        &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; Main(&lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt;[] args)
        {
            SqlCeConnection conn = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; SqlCeConnection(&lt;SPAN class=str&gt;"c:\temp\abc.sdf"&lt;/SPAN&gt;);
            &lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; (conn)
            {
                conn.Open();
                DbSyncScopeDescription desc = GetDbSyncDescription(conn);

                &lt;SPAN class=rem&gt;//Check and sync enable the Compact database&lt;/SPAN&gt;
                SqlCeSyncScopeProvisioning ceScope = 
                    &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; SqlCeSyncScopeProvisioning(desc);
                &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (!ceScope.ScopeExists(scopeName, conn))
                {
                    ceScope.Apply(conn);
                }

                SqlConnection azConn = 
                    &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; SqlConnection(&lt;SPAN class=str&gt;"YourSqlAzureConnectionString"&lt;/SPAN&gt;);
                &lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; (azConn)
                {
                    azConn.Open();
                    &lt;SPAN class=rem&gt;//Check and sync enable the SQL Azure database&lt;/SPAN&gt;
                    SqlAzureSyncScopeProvisioning azScope = 
                        &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; SqlAzureSyncScopeProvisioning(desc);
                    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (!azScope.ScopeExists(scopeName, azConn))
                    {
                        azScope.Apply(azConn);
                    }
                }
            }
        }

        &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt;[] tableNames = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt;[] { &lt;SPAN class=str&gt;"Foo"&lt;/SPAN&gt;, &lt;SPAN class=str&gt;"Bar"&lt;/SPAN&gt; };
        &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; scopeName = &lt;SPAN class=str&gt;"FooBarScope"&lt;/SPAN&gt;;
        &lt;SPAN class=kwrd&gt;private&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; DbSyncScopeDescription GetDbSyncDescription
            (SqlCeConnection conn)
        {
            DbSyncScopeDescription desc = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; DbSyncScopeDescription();

            &lt;SPAN class=rem&gt;/***&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;             * Option 1 for generating schema - Iterate through the list &lt;/SPAN&gt;
&lt;SPAN class=rem&gt;             * of tables you need and get description for them&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;             */&lt;/SPAN&gt; 
            &lt;SPAN class=kwrd&gt;foreach&lt;/SPAN&gt; (&lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; table &lt;SPAN class=kwrd&gt;in&lt;/SPAN&gt; tableNames)
            {&lt;/PRE&gt;&lt;PRE class=csharpcode&gt;                desc.Tables.Add(
                    SqlCeSyncDescriptionBuilder.GetDescriptionForTable
                    (&lt;FONT color=#000000&gt;&lt;SPAN class=str&gt;table&lt;/SPAN&gt;, conn));&lt;/FONT&gt;&lt;/PRE&gt;
&lt;STYLE type=text/css&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/STYLE&gt;
&lt;PRE class=csharpcode&gt;            }

            &lt;SPAN class=rem&gt;/***&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;             * Option 2 for generating schema - If you already have a &lt;/SPAN&gt;
&lt;SPAN class=rem&gt;             * Compact database provisioned for sync you&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;             * could just read the whole scope description from it.&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;             **/&lt;/SPAN&gt;
            &lt;SPAN class=rem&gt;// desc = SqlCeSyncDescriptionBuilder.GetDescriptionForScope(&lt;/SPAN&gt;
            &lt;SPAN class=rem&gt;// scopeName, conn);&lt;/SPAN&gt;

            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; desc;
        }
    }
}&lt;/PRE&gt;
&lt;STYLE type=text/css&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/STYLE&gt;

&lt;STYLE type=text/css&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/STYLE&gt;

&lt;P&gt;To move from SQL Azure to SQL Server you just need to replace SqlCeSyncScopeDescription type with SqlSyncScopeDescription. To access the new types under Microsoft.Synchronization.Data.SqlAzure just add a reference to the dll of the same name found under &lt;STRONG&gt;%programfiles%\Microsoft Sync Framework\Power pack For Sql azure November CTP\&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Maheshwar Jayaraman&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9924973" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Framework/">Sync Framework</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Services+for+ADO-NET/">Sync Services for ADO.NET</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Project+Huron/">Project Huron</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/SQL+Azure/">SQL Azure</category></item><item><title>Announcing Microsoft Sync Framework Power Pack For SQL Azure CTP</title><link>http://blogs.msdn.com/b/mahjayar/archive/2009/11/17/announcing-microsoft-sync-framework-power-pack-for-sql-azure-ctp.aspx</link><pubDate>Tue, 17 Nov 2009 19:15:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9923785</guid><dc:creator>mahjayar</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/mahjayar/rsscomments.aspx?WeblogPostID=9923785</wfw:commentRss><comments>http://blogs.msdn.com/b/mahjayar/archive/2009/11/17/announcing-microsoft-sync-framework-power-pack-for-sql-azure-ctp.aspx#comments</comments><description>&lt;P&gt;PDC 2009 starts today and Ray Ozzie and Bob Muglia kicked off todays keynote presentation. It gives me great pleasure to announce the public availability of the MSF power pack for SQL Azure. Its a CTP and we are really excited to see people download this and provide feedback around the direction we are heading w.r.t providing a synchronization story for SQL Azure. Head over to &lt;A href="http://tinyurl.com/yhn76rr"&gt;&lt;STRONG&gt;http://tinyurl.com/yhn76rr&lt;/STRONG&gt;&lt;/A&gt;&lt;STRONG&gt; &lt;/STRONG&gt;to download the Power pack. &lt;/P&gt;
&lt;P&gt;The power pack provides the following components.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;SQL Azure Data Sync Tool for SQL Server -&lt;/STRONG&gt; This is a automated tool to migrate your on premise SQL server data to SQL Azure by setting up a strong synchronization relationship. Kelly Blue Book demonstrated this in the key note when they moved a table from their on premise database to SQL Azure.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;SqlAzureSyncProvider &lt;/STRONG&gt;- Power pack also brings in a new dll, named Microsoft.Synchronization.Data.SqlAzure.dll, that contains a brand new provider, SqlAzureProvider, that enables existing database providers to synchronize with SQL Azure. This also has the new SQL Azure specific Sync metadata provisioning API's.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Sql Azure Offline Visual Studio Plug-In - &lt;/STRONG&gt;This adds a new item template for VS 2008 SP1 that enables you to setup offline synchronization relationships with SQL Azure.&lt;/P&gt;
&lt;P&gt;The team has worked really hard to bring this to you and we would love any feedback you got. You can use the email feature here or send email to &lt;STRONG&gt;syncfdbk &lt;/STRONG&gt;at &lt;STRONG&gt;microsoft&lt;/STRONG&gt; dot &lt;STRONG&gt;com &lt;/STRONG&gt;with your feedback.&lt;/P&gt;
&lt;P&gt;We first discussed about Project "Huron" at last year's PDC and with this CTP we have taken the first steps toward the vision of a Data Hub in the sky. We have a more detailed post about this over at our Sync blog. Refer &lt;A href="http://blogs.msdn.com/sync/archive/2009/11/17/announcing-sql-azure-data-sync-november-ctp-available-for-download.aspx"&gt;http://blogs.msdn.com/sync/archive/2009/11/17/announcing-sql-azure-data-sync-november-ctp-available-for-download.aspx&lt;/A&gt;.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Mark Scurell, our lead PM, will be demonstrating this whole end to end walkthrough in his talk on Thursday 11/19 at 3 PM. For more information refer &lt;A href="http://microsoftpdc.com/Sessions/SVC23"&gt;http://microsoftpdc.com/Sessions/SVC23&lt;/A&gt;. He will take you through the process of synchronizing an on-premise database with SQL Azure, generate an offline cache from SQL Azure down to a SQL Server Compact database and move data between the client, SQL Azure and on-premise server all with just &lt;STRONG&gt;one single line of code&lt;/STRONG&gt;. &lt;/P&gt;
&lt;P&gt;Maheshwar Jayaraman&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9923785" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Framework/">Sync Framework</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Services+for+ADO-NET/">Sync Services for ADO.NET</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Project+Huron/">Project Huron</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/SQL+Azure/">SQL Azure</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/MSF+Power+Pack+For+Sql+Azure/">MSF Power Pack For Sql Azure</category></item><item><title>MSF V2 DeepDive – Batching Directory and Batch Files</title><link>http://blogs.msdn.com/b/mahjayar/archive/2009/11/16/msf-v2-deepdive-batching-directory-and-batch-files.aspx</link><pubDate>Mon, 16 Nov 2009 22:15:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9923203</guid><dc:creator>mahjayar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/mahjayar/rsscomments.aspx?WeblogPostID=9923203</wfw:commentRss><comments>http://blogs.msdn.com/b/mahjayar/archive/2009/11/16/msf-v2-deepdive-batching-directory-and-batch-files.aspx#comments</comments><description>&lt;P align=justify&gt;This is a continuation from the previous post I did explaining the new memory based batching feature for Database providers in MSF V2. Please refer to that post at &lt;A title="MSF V2 CTP2 Deep Dive – Memory Based Batching" href="http://blogs.msdn.com/mahjayar/archive/2009/09/16/msf-v2-ctp2-deep-dive-memory-based-batching.aspx" mce_href="http://blogs.msdn.com/mahjayar/archive/2009/09/16/msf-v2-ctp2-deep-dive-memory-based-batching.aspx"&gt;MSF V2 CTP2 Deep Dive – Memory Based Batching&lt;/A&gt;. This is probably a good time to mention that the final version of MSF V2 has been released to web and can be downloaded from &lt;A title=http://msdn.microsoft.com/en-us/sync/default.aspx href="http://msdn.microsoft.com/en-us/sync/default.aspx" mce_href="http://msdn.microsoft.com/en-us/sync/default.aspx"&gt;http://msdn.microsoft.com/en-us/sync/default.aspx&lt;/A&gt;.&lt;/P&gt;
&lt;P align=justify&gt;Database providers chunks up changes by spooling changes to the file system. These chunks, or batch files, are later transferred to the remote provider which applies them in the correct order. At any given point the &lt;STRONG&gt;&lt;EM&gt;runtime&lt;/EM&gt;&lt;/STRONG&gt; will be processing at most one batch file. Notice the emphasis on runtime. Any user specified event operating on the DataSet property would result in more than one batch file live in memory. Batches are spooled to the file system by the enumerating provider and the provider uses the &lt;STRONG&gt;RelationalSyncProvider.BatchingDirectory&lt;/STRONG&gt; property on the enumerating provider to detect the base directory to use. For each sync the runtime will create a unique directory inside the base directory. The name of the base directory is of the format &lt;STRONG&gt;Sync_XXXXXXXXXXXX&lt;/STRONG&gt;. The directory name is unique for the two providers currently synchronizing and the name does not change for subsequent syncs. This allows the runtime to detect “failed” synchronization attempts so it can resume from the failed point. More on the “Sync Resume”&amp;nbsp; feature later. Inside that directory the runtime will spool one&amp;nbsp; &lt;STRONG&gt;SyncBatchHeaderFile.sync&lt;/STRONG&gt; file and one or more &lt;STRONG&gt;.batch&lt;/STRONG&gt; files. The &lt;STRONG&gt;.sync&lt;/STRONG&gt; file is the metadata file that contains metadata on the current sync session. It holds some key information such as the Version, MadeWithKnowledge and DestinationKnowledge. The .batch files contain the raw change data that needs to be applied on the destination. The .batch file is just a binary serialized version of the &lt;STRONG&gt;DbSyncBatchInfo&lt;/STRONG&gt; type. The batch info type contains both the actual data and the metadata corresponding to that data. For faster access to the metadata the runtime serializes the metadata separately from the data. Here is the definition of the DbSyncBatchInfo type.&lt;/P&gt;
&lt;DIV class=csharpcode&gt;&lt;PRE class=alt&gt;&lt;SPAN class=lnum&gt;   1:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; DbSyncBatchInfo : IDisposable&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   2:  &lt;/SPAN&gt;    {&lt;/PRE&gt;&lt;PRE class=alt&gt;&lt;SPAN class=lnum&gt;   3:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; DbSyncBatchInfo();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   4:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;long&lt;/SPAN&gt; DataCacheSize { get; set; }&lt;/PRE&gt;&lt;PRE class=alt&gt;&lt;SPAN class=lnum&gt;   5:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; DataSetSurrogate DataSetSurrogate { get; set; }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   6:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; Id { get; set; }&lt;/PRE&gt;&lt;PRE class=alt&gt;&lt;SPAN class=lnum&gt;   7:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;bool&lt;/SPAN&gt; IsLastBatch { get; set; }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   8:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt; SequenceNumber { get; set; }&lt;/PRE&gt;&lt;PRE class=alt&gt;&lt;SPAN class=lnum&gt;   9:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; Version Version { get; set; }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  10:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; Dispose();&lt;/PRE&gt;&lt;PRE class=alt&gt;&lt;SPAN class=lnum&gt;  11:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;protected&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;virtual&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; Dispose(&lt;SPAN class=kwrd&gt;bool&lt;/SPAN&gt; cleanup);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  12:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;byte&lt;/SPAN&gt;[] GetLearnedKnowledge();&lt;/PRE&gt;&lt;PRE class=alt&gt;&lt;SPAN class=lnum&gt;  13:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; SetLearnedKnowledge(&lt;SPAN class=kwrd&gt;byte&lt;/SPAN&gt;[] knowledgeBytes);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  14:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;override&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; ToString();&lt;/PRE&gt;&lt;PRE class=alt&gt;&lt;SPAN class=lnum&gt;  15:  &lt;/SPAN&gt;    }&lt;/PRE&gt;&lt;/DIV&gt;
&lt;STYLE type=text/css&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/STYLE&gt;

&lt;P align=justify&gt;The actual data is contained in the DataSetSurrogate property while the rest of the properties are just the metadata for that data. Some key metadata items are&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;&lt;STRONG&gt;Version&lt;/STRONG&gt; – Batching version of the provider that generated this batch. This enables the destination runtime to apply versioning rules when consuming batches generated from an older version.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;&lt;STRONG&gt;Id&lt;/STRONG&gt; – Unique id of this batch&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;&lt;STRONG&gt;SequenceNumber&lt;/STRONG&gt; – This is used by the destination to ensure that batches are applied in the same order they were generated in. This will ensure that batch files arriving out of order at the destination are still consumed in the correct sequence.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;&lt;STRONG&gt;DataCacheSize&lt;/STRONG&gt; – Represents the deserialized size of the data.&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P align=justify&gt;With the RTM version we exposed this type out to the user. This change was made to accommodate feedback from users that they wanted to override the default BinarySerializer or in some cases completely move off DataSet as a data transfer medium. With this type public, users can now easily deserialize any .batch file and provider their customizations on top of that. Each batch file contains two binary objects. The first one is the actual DbSyncBatchInfo type sans the actual data followed by the serialized version of DataSertSurrogate. Users customizing this part of the runtime should pay attention to the format. I have attached a simple factory class DbSyncBatchInfoFactory.cs that can serialize and deserialize any batch file.&lt;/P&gt;
&lt;H1&gt;&lt;STRONG&gt;Resuming Sync Session&lt;/STRONG&gt;&lt;/H1&gt;
&lt;P align=justify&gt;I had earlier mentioned that the runtime uses a unique reproducible directory name for storing batch files whenever it enumerates changes for a provider. This is so that the runtime can attempt to restart earlier failed sync session. There are many reasons for sync session abruptions but the most common one users face is transient network disconnections. Flaky network connections is quite a common issue with mobile users. Users would have restart a sync session if their network connectivity gets dropped in between. This meant that they had to download/upload all changes back to the remote server. This also means that the remote Sql Server is wasting precious CPU time enumerating the same changes over and over. &lt;/P&gt;
&lt;P align=justify&gt;To avoid re-enumerating changes the enumerating provider will check to see if any batch files exist prior to spawning a new “Select” query. If any batch files for the current remote provider exists, the runtime will inspect the files to see if it can reuse those files. Several factors are considered to determine batch reusability such as state of enumeration, destination knowledge etc. The runtime uses the metadata from the SyncBatchHeaderFile.sync to check if existing batch files are relevant for the current state of the destination. If it determines that the files are relevant then it will pick up enumeration from where the older sync left off. This means if a table had changes between the first failed sync session and the restart only those changes would be picked up. If the runtime determines that the existing batch files are not relevant (destination got changes from a different peer or one of the batch files is corrupt of missing or the enumeration was incomplete the first time) all batch files are deleted and a fresh enumeration query is launched.&lt;/P&gt;
&lt;P align=justify&gt;This batching directory is usually cleaned up by the runtime after it successfully applies all changes. Users can override this behavior by setting RelationalSyncProvider.CleanupBatchingDirectory property to false. &lt;/P&gt;
&lt;H1&gt;&amp;nbsp;&lt;/H1&gt;
&lt;H1&gt;Batch Files Cleanup In Mid Tier&lt;/H1&gt;
&lt;P align=justify&gt;If in case users are using a mid tier to communicate with Sql Server then you would need a background job that constantly monitors the batching folder to delete any files older than a certain time. This is needed because the runtime cleanup of the batch files happens only on the destination provider after a successful application (to enable sync restart feature). &lt;/P&gt;
&lt;H1&gt;Anti-Virus tools and Batching&lt;/H1&gt;
&lt;P align=justify&gt;One note of caution to users having real time anti-virus scanning tools. Please exclude the batching directory from real time scan so that there is no file contention between the sync runtime and the virus scan runtime.&lt;/P&gt;
&lt;P align=justify&gt;Maheshwar Jayaraman&lt;/P&gt;
&lt;DIV style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id=scid:0767317B-992E-4b12-91E0-4F059A8CECA8:8a7b03a6-cc19-48f9-a26b-94adc232efab class=wlWriterEditableSmartContent&gt;Technorati Tags: &lt;A href="http://technorati.com/tags/DbSyncProvider" rel=tag mce_href="http://technorati.com/tags/DbSyncProvider"&gt;DbSyncProvider&lt;/A&gt;,&lt;A href="http://technorati.com/tags/Sync+Framework" rel=tag mce_href="http://technorati.com/tags/Sync+Framework"&gt;Sync Framework&lt;/A&gt;,&lt;A href="http://technorati.com/tags/Sync+Services+For+ADO.NET" rel=tag mce_href="http://technorati.com/tags/Sync+Services+For+ADO.NET"&gt;Sync Services For ADO.NET&lt;/A&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9923203" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-09-92-32-03/DbSyncBatchInfoFactory_2E00_cs" length="1469" type="text/plain" /><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Framework/">Sync Framework</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Services+for+ADO-NET/">Sync Services for ADO.NET</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/DbSyncProvider/">DbSyncProvider</category></item><item><title>PDC 2009 and Sync related sessions</title><link>http://blogs.msdn.com/b/mahjayar/archive/2009/11/13/pdc-2009-and-sync-related-sessions.aspx</link><pubDate>Fri, 13 Nov 2009 21:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9922252</guid><dc:creator>mahjayar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/mahjayar/rsscomments.aspx?WeblogPostID=9922252</wfw:commentRss><comments>http://blogs.msdn.com/b/mahjayar/archive/2009/11/13/pdc-2009-and-sync-related-sessions.aspx#comments</comments><description>&lt;P&gt;PDC 2009 is next week and I wanted to have a quick post on some of the sessions about Microsoft Sync Framework. &lt;/P&gt;
&lt;DIV class=UIShareStage_Title&gt;&lt;SPAN&gt;&lt;A class="UIShareStage_InlineEdit inline_edit" onclick='new InlineEditor(this, "attachment[params][title]", false); return false;'&gt;&lt;STRONG&gt;Using the Microsoft Sync Framework to Connect Apps to the Cloud &lt;/STRONG&gt;&lt;/A&gt;&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;DIV class=UIShareStage_Title&gt;&lt;A href="http://microsoftpdc.com/Sessions/SVC23"&gt;http://microsoftpdc.com/Sessions/SVC23&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV class=UIShareStage_Title&gt;&amp;nbsp;- &lt;A class="UIShareStage_InlineEdit inline_edit" onclick='new InlineEditor(this, "attachment[params][summary]", true); return false;'&gt;Come hear how the Microsoft Sync Framework can be used to bridge on-premises data to SQL Azure and Windows Azure storage.&amp;nbsp; Learn to quickly build applications that use the cloud as a data hub for aggregation of enterprise, partner, desktop and device data&lt;/A&gt;.&lt;/DIV&gt;
&lt;DIV class=UIShareStage_Title&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV class=UIShareStage_Title&gt;You should hear more about Sync Framework in some of the Sql Azure sessions as well. Will have more details to share after next Tuesday.&lt;/DIV&gt;
&lt;DIV class=UIShareStage_Title&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV class=UIShareStage_Title&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=c4afdd181722240a416057 class="UIShareStage_ThumbPagerControl UIThumbPagerControl UIThumbPagerControl_First "&gt;
&lt;DIV class=UIThumbPagerControl_Buttons&gt;&lt;A class="UIThumbPagerControl_Button UIThumbPagerControl_Button_Left"&gt;&lt;/A&gt;&lt;A class="UIThumbPagerControl_Button UIThumbPagerControl_Button_Right"&gt;&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV class=UIThumbPagerControl_Text&gt;&lt;LABEL id=label_no_picture for=no_picture&gt;&lt;STRONG&gt;&lt;FONT color=#666666&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/LABEL&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9922252" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Framework/">Sync Framework</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Services+for+ADO-NET/">Sync Services for ADO.NET</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Windows+Azure/">Windows Azure</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/SQL+Azure/">SQL Azure</category></item><item><title>MSF V2 CTP2 Deep Dive – Memory Based Batching</title><link>http://blogs.msdn.com/b/mahjayar/archive/2009/09/16/msf-v2-ctp2-deep-dive-memory-based-batching.aspx</link><pubDate>Thu, 17 Sep 2009 02:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9896105</guid><dc:creator>mahjayar</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/mahjayar/rsscomments.aspx?WeblogPostID=9896105</wfw:commentRss><comments>http://blogs.msdn.com/b/mahjayar/archive/2009/09/16/msf-v2-ctp2-deep-dive-memory-based-batching.aspx#comments</comments><description>&lt;P align=justify&gt;Its been quite a while since I posted about MSF v2 CTP2. As promised in my earlier posts I will be doing a series of deep-dive of the new SyncServices features added in MSF V2 CTP2. Today I am starting off with the Batching feature.&lt;/P&gt;
&lt;P align=justify&gt;One of the most common feedback we received with the peer providers shipped for MSF V1 was the inability to sync changes in batches. Customer using DbSyncProvider always complained of OutOfMemory exceptions when synchronizing large data across databases. The MSF workflow did support the notion of batching but the relational peer providers did not take advantage of the feature. &lt;/P&gt;
&lt;H1&gt;Background:&lt;/H1&gt;
&lt;P align=justify&gt;When we decided to support batching we looked back at how the hub-spoke providers supported batching. For the hub-spoke we supported batched download of data from server by modifying the enumeration query to return rows in batches. Even though this solved the issue of OOM with large data it had some inherent limitations. Some of the problems were&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;Code has to be hand coded by the user for each sync schema which meant a higher probability of user error.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;Batching was not supported for uploads from the clients.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;There was no easy way to estimate the number of batches you would need. The solution computed batch size by dividing the current tickcount with the last sent tick count for any table. This meant that the batch size was fixed even if the table had 0 changes between the last sent and the current time instance. This meant that the SyncAgent would return empty batches.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;Batching was based on number of rows which made it harder to predict when data will be too big. &lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;In general usability was hindered as the batching SP was complex and highly involved. The SP became more complex if the anchors were non timestamp based.&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P align=justify&gt;One other problem unique to the peer providers was the use of SyncKnowledge to compute the changes that needs to be synchronized. In hub-spoke these were simple timestamp anchors that users used to compute what has changed in a table and each table had its own anchor which did not collide with other tables. In peer providers the SyncKnowledge represents the “knowledge” of all tables for a given Sync scope. Any disparity in what the knowledge represents about a replica and the actual data would mean data will not synchronize and result in data non-convergence in your sync topology. &lt;/P&gt;
&lt;H1&gt;Motivation for Batching:&lt;/H1&gt;
&lt;P align=justify&gt;When we designed batching we wanted to address all the above shortcomings. We also wanted to reduce the probability of user errors when computing batches. The primary notion of batching would be to avoid running out of memory when synchronizing large amounts of data. The most straight forward way to support batching would be to batch by rows. This works for most cases but does the solve the problem mentioned earlier – how does the user compute how many rows can the client handle. A desktop machine might have enough processing power to consume 10,000 rows at a time but a hand held device might only be able to handle 100 rows. Moreover on a desktop the sync session has to share the available memory which meant that on high loads the number of rows that a sync session can handle without going out of memory rapidly declines. &lt;/P&gt;
&lt;P align=justify&gt;The primary goal of the sync developer is to successfully sync data over from one replica to another without running out of memory. Basically the one and only goal of batching is to ensure that incremental progress can be made with the available memory resource on the machine. Since one of the most deterministic resource a developer has control over is the available memory, we decided to design batching around memory usage. The developer would put a limit on the max amount on the size of data being synchronized. This works wonderfully well as it makes batching an on demand operation. If row based batching was used then the system would have to send ‘N’ batches no matter how small the individual rows were of. In the memory based batching if all changes required to send to the destination fits within the max size specified then batching is bypassed.&lt;/P&gt;
&lt;P align=justify&gt;We also wanted to make it support batching for all kinds of relational stores (Sql, Sql CE and any ADO.NET capable database). We wanted to achieve all of this with as little input from the user as possible. We did not want customers to reinvent the wheel around batching logic for every sync application they wrote.&lt;/P&gt;
&lt;H1&gt;&lt;STRONG&gt;Batching Workflow:&lt;/STRONG&gt;&lt;/H1&gt;
&lt;P align=justify&gt;With the motivations for batching being clear we decided to enable batching via a simple switch on the &lt;STRONG&gt;RelationalSyncProvider&lt;/STRONG&gt;. We added a new property, &lt;STRONG&gt;MemoryDataCacheSize&lt;/STRONG&gt;", which users can set to limit the amount of memory used (in KB) by the synchronizing rows. Data cache limit can be set on both providers and the runtime will use the lower size to ensure that one peer does not send data that cannot be handled by the destination. Sync runtime will revert to batched mode even if one peer has not specified a cache size.&lt;/P&gt;
&lt;H2&gt;Batched Enumeration:&lt;/H2&gt;
&lt;P align=justify&gt;The workflow of batching is quite simple. Destination providers communicate its cache size by returning it to the &lt;STRONG&gt;SyncOrchestrator&lt;/STRONG&gt; in its &lt;STRONG&gt;GetSyncBatchParameters&lt;/STRONG&gt;() call. This in-turn is passed to the enumerating peer in the &lt;STRONG&gt;GetChangeBatch&lt;/STRONG&gt;() call. Here is the simple workflow of the batched enumeration process.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;If batching is enabled then start a background thread that will compute the enumeration.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;Runtime starts by querying the list of tables mentioned in the &lt;STRONG&gt;DbSyncAdapters&lt;/STRONG&gt; list.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;For each table it retrieves the ADO.NET &lt;STRONG&gt;DataReader&lt;/STRONG&gt; for its corresponding enum query.&lt;/DIV&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;For each row, before reading the column values, it computes the size of the row.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;If current_Data_Cache_Size + Next_Row_Size &amp;lt;= (110% * &lt;STRONG&gt;MemoryDataCacheSize&lt;/STRONG&gt;) specified then it reads the row in to memory.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;If pulling in the new row exceeds the specified &lt;STRONG&gt;MemoryDataCacheSize&lt;/STRONG&gt; it spools the current in memory rows to a file. It then cleans up its data cache and continues reading changes.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;Batches are spooled in the user specified directory configured on &lt;STRONG&gt;RelationalSyncProvider.BatchingDirectory&lt;/STRONG&gt; property.&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV align=justify&gt;The above steps are repeated till all the tables have been enumerated.&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P align=justify&gt;As you can see batch files are spooled to disk only when the data exceeds the memory size specified. If all changes fit in memory then the system reverts back to non batching mode where all changes are sent to destination in memory.&lt;/P&gt;
&lt;P align=justify&gt;The runtime will try to stuff a batch with data as long as the in-memory size of those data does not exceed the specified batch size by 10%. This is to guard against sending many number of under populated batches.&lt;/P&gt;
&lt;P align=justify&gt;There are times when a single row would be greater than 110% of the specified data cache size. In such cases the runtime errors out with an exception message that lists the offending table and the primary key of the row that is too big. Users would need to increase the data cache size to accommodate that row.&lt;/P&gt;
&lt;P align=justify&gt;Since enumeration happens in the background, we employ a prodcuer/consumer model between the main threads &lt;STRONG&gt;GetChangeBatch&lt;/STRONG&gt;() call and the background enumeration thread. The main consumer thread will block till the producer spools a batch (or reverts to non batched mode if all changes fit in memory) and report this batch information to the destination provider.&lt;/P&gt;
&lt;H2&gt;Batched Apply:&lt;/H2&gt;
&lt;P align=justify&gt;Relational providers uses the type &lt;STRONG&gt;DbSyncContext&lt;/STRONG&gt; to communicate changes between the source and the destination providers. With batching we have added three new properties to this type to facilitate working with batches. The three properties added are&lt;/P&gt;
&lt;P&gt;public string BatchFileName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { get; set; } ==&amp;gt; Points to the actual spooled batch file.&lt;/P&gt;
&lt;P&gt;public string IsLastBatch&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { get; set; }&lt;/P&gt;
&lt;P&gt;public string IsDataBatched&amp;nbsp;&amp;nbsp;&amp;nbsp; { get; set; }&lt;/P&gt;
&lt;P align=justify&gt;When the destination receives a batched &lt;STRONG&gt;DbSyncContext&lt;/STRONG&gt; it will queue the context. It will queue all batches till it receives the last batch at which point it will open a transaction, deserialize each batch, apply its contents and then finally commit the transaction. Destination provider will apply the batches in the same FIFO order it received them from the source provider.&lt;/P&gt;
&lt;H2&gt;Tombstone Application:&lt;/H2&gt;
&lt;P align=justify&gt;Relational providers usually applies changes in the following order. DELETES followed by INSERTS and UPDATES. Order in which these changes are applied is usually dictated by the order in which the users specify their table adapters. The adapter order assumes that related tables (PK/FK) and ordered correctly.&amp;nbsp; For DELETES, the runtime will apply changes in the reverse adapter order to ensure that child table DELETES are applied first before parent table DELETES to avoid RI violations. Since batches are applied in FIFO order its plausible that the current batch may not contain the child table DELETES. Within a given batch the runtime continues to apply DELETES in reverse order. In the case where the child table is not in current batch the runtime will recognize the SQL errors for those tombstones and queue them up for retry. When all batches have been applied, the runtime will revisit this queued up DELETES and retry applying them. At this point all of the parent deletes should succeed as the dependent child entries should have already been applied.&lt;/P&gt;
&lt;P align=justify&gt;Note that batching does not change any runtime logic related to conflicts handing. Batching only governs the number of rows in memory at any given point of time and nothing else. The only thing you have to guard in your &lt;STRONG&gt;ApplyChangeFailed&lt;/STRONG&gt; event handler is the above mentioned case where a PK delete fails.&lt;/P&gt;
&lt;H1&gt;Batching Assumptions:&lt;/H1&gt;
&lt;UL&gt;
&lt;LI&gt;Sync runtime has full Read/Write access to the directory specified in the &lt;STRONG&gt;BatchingDirectory&lt;/STRONG&gt; property. &lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;MemoryDataCacheSize&lt;/STRONG&gt; only applies to the memory used for reading sync rows. It does not guard against overall process memory usage. &lt;/LI&gt;
&lt;LI&gt;Batches are applied in the order they are received by the destination provider. &lt;/LI&gt;&lt;/UL&gt;
&lt;H1&gt;So, Does It Work?&lt;/H1&gt;
&lt;P align=justify&gt;Moment of truth is whether all this batching thingy works and does it prevent process from running out of memory. I coded up a simple scenario which syncs two tables, Orders and OrderDetails, from a Sql server down to a CE client. The schema for the two tables is quite simple.&lt;/P&gt;
&lt;P&gt;//Orders &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; orderid - int, PK &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; orderdate – datetime&lt;/P&gt;
&lt;P align=justify&gt;&lt;BR&gt;//OrderDetails &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; orderdetailsid - id, PK &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; orderid - int &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; product - varchar(max) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; quantity –int&lt;/P&gt;
&lt;P align=justify&gt;I populated the tables with about 25,000 rows each. Each row in OrderDetails is about 8K in size and each row in orders is about 50 bytes in size. The demo computes the max working set of the process for reporting purposes. I did two runs one without batching and one with batching. Here is the comparison between the two runs.&lt;/P&gt;
&lt;TABLE border=0 cellSpacing=0 cellPadding=2 width=375&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=131&gt;&lt;STRONG&gt;Sync Type&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=131&gt;&lt;STRONG&gt;Peak Working Set (MB)&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=111&gt;&lt;STRONG&gt;Memory Use percent&lt;/STRONG&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=140&gt;Non Batched&lt;/TD&gt;
&lt;TD vAlign=top width=137&gt;446&lt;/TD&gt;
&lt;TD vAlign=top width=115&gt;NA&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=142&gt;Batched (1 MB batch Size)&lt;/TD&gt;
&lt;TD vAlign=top width=139&gt;47&lt;/TD&gt;
&lt;TD vAlign=top width=117&gt;10.53&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=142&gt;Batched (5 MB batch Size)&lt;/TD&gt;
&lt;TD vAlign=top width=139&gt;59&lt;/TD&gt;
&lt;TD vAlign=top width=119&gt;13.2&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=141&gt;Batched (10 MB batch Size)&lt;/TD&gt;
&lt;TD vAlign=top width=139&gt;78&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;17.45&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P align=justify&gt;As you can see that batching uses approximately 10-20% of the non batched memory for the above sample. This is not to be an indication of memory savings for all kinds of schemas. Feel free to try it with your real world schemas and I am sure you will see considerable improvements.&lt;/P&gt;
&lt;P align=justify&gt;Here is the procmon output for the non-batched case. As you can see the memory utilization keeps climbing till all changes are read in memory.&lt;/P&gt;
&lt;P align=justify&gt;&lt;A href="http://blogs.msdn.com/blogfiles/mahjayar/WindowsLiveWriter/MSFV2CTP2DeepDiveBatching_C4EE/image_2.png" mce_href="http://blogs.msdn.com/blogfiles/mahjayar/WindowsLiveWriter/MSFV2CTP2DeepDiveBatching_C4EE/image_2.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/mahjayar/WindowsLiveWriter/MSFV2CTP2DeepDiveBatching_C4EE/image_thumb.png" width=494 height=666 mce_src="http://blogs.msdn.com/blogfiles/mahjayar/WindowsLiveWriter/MSFV2CTP2DeepDiveBatching_C4EE/image_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Here is the procmon for the same demo when batching is enabled. You can see that the runtime goes to 31 MB initially and then settles in to a nice pattern as files are spooled and then consumed by the destination.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/mahjayar/WindowsLiveWriter/MSFV2CTP2DeepDiveBatching_C4EE/image_4.png" mce_href="http://blogs.msdn.com/blogfiles/mahjayar/WindowsLiveWriter/MSFV2CTP2DeepDiveBatching_C4EE/image_4.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/mahjayar/WindowsLiveWriter/MSFV2CTP2DeepDiveBatching_C4EE/image_thumb_1.png" width=465 height=626 mce_src="http://blogs.msdn.com/blogfiles/mahjayar/WindowsLiveWriter/MSFV2CTP2DeepDiveBatching_C4EE/image_thumb_1.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Here is the MSDN doc link for the batching feature. &lt;A href="http://msdn.microsoft.com/en-us/library/dd918908(SQL.105).aspx"&gt;http://msdn.microsoft.com/en-us/library/dd918908(SQL.105).aspx&lt;/A&gt;. &amp;nbsp;Feel free to comment here is you have any specific questions.&lt;/P&gt;
&lt;P&gt;Next- Detailed look at the batch file.&lt;/P&gt;
&lt;P&gt;Maheshwar Jayaraman&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9896105" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Framework/">Sync Framework</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/Sync+Services+for+ADO-NET/">Sync Services for ADO.NET</category><category domain="http://blogs.msdn.com/b/mahjayar/archive/tags/DbSyncProvider/">DbSyncProvider</category></item></channel></rss>