08/11/2010 16:57:49


1. Database Provisioning

a. Configuration settings of SqlSyncScopeProvisioning apply only to tables already added to the object

The Microsoft.Synchronization.Data.SqlServer.SqlSyncScopeProvisioning class contains several methods to set configuration options that control how a scope is synchronized, such as the SetCreateTableDefault or SetUseBulkProceduresDefault methods. The configuration options that these settings refer to are created for each table that is contained in the scope, and the settings take effect only for tables that are contained in the SqlSyncScopeProvisioning.Tables collection at the time the configuration option is specified. For example, the following code creates a SqlSyncScopeProvisioning object and two DbSyncTableDescription objects. The first table, myTable1, is added to the scope and SetUseBulkProceduresDefault(false) is called. This method sets the bulk procedures configuration option to false only for myTable1. This is because the method configures only the tables that are contained in the scope at the time the method is called. Therefore, when myTable2 is added to the scope, it is configured to use bulk procedures because that is the default configuration. When Apply is called to provision the scope, bulk procedures are not created for myTable1 but they are created for myTable2.

 
// Create scope and tables.
DbSyncScopeDescription myScope = new DbSyncScopeDescription("myScope");
SqlSyncScopeProvisioning prov = new SqlSyncScopeProvisioning(conn, myScope);
DbSyncTableDescription myTable1 =
SqlSyncDescriptionBuilder.GetDescriptionForTable("myTable1", conn);
DbSyncTableDescription myTable2 =
SqlSyncDescriptionBuilder.GetDescriptionForTable("myTable2", conn);

// Add myTable1 to the scope. Bulk procedures are currently turned on
// for myTable1 because that is the default setting.
myScope.Tables.Add(myTable1);

// This method turns off the use of bulk procedures for myTable1,
// because it is the only table in the scope. myTable2 is not affected.
prov.SetUseBulkProceduresDefault(false);

// Add myTable2 to the scope. Bulk procedures are currently turned on
// for myTable2 because that is the default setting.
myScope.Tables.Add(myTable2);

// myTable1 is provisioned with no bulk procedures.
// myTable2 is provisioned with bulk procedures.
prov.Apply();

To avoid this situation, add all tables to your scope before calling any of the methods that set configuration options, as in the following example.

 
// Create scope and tables.
DbSyncScopeDescription myScope = new DbSyncScopeDescription("myScope");
SqlSyncScopeProvisioning prov = new SqlSyncScopeProvisioning(conn, myScope);
DbSyncTableDescription myTable1 =
SqlSyncDescriptionBuilder.GetDescriptionForTable("myTable1", conn);
DbSyncTableDescription myTable2 =
SqlSyncDescriptionBuilder.GetDescriptionForTable("myTable2", conn);

// Add myTable1 and myTable2 to the scope.
myScope.Tables.Add(myTable1);
myScope.Tables.Add(myTable2);

// Turn off the use of bulk procedures for all tables in the scope.
prov.SetUseBulkProceduresDefault(false);

// myTable1 and myTable2 are both provisioned with no bulk procedures.
prov.Apply();

For more information about provisioning, see How to: Provision and Deprovision Synchronization Scopes and Templates (SQL Server) in the documentation.

b. Supported scenarios for concurrent actions while provisioning a scope

Simultaneously performing another action on a database that is in the process of being provisioned is supported in some scenarios. In other situations, this might cause failures or unexpected results. The following list describes the supported scenarios as well as situations to avoid.

  • When you create two or more scopes from the same template, you can provision them concurrently to the same database.

  • When you create two or more scopes that are not from the same template, or are not based on templates, provisioning them concurrently to the same database may produce unexpected results, such as deadlocks in the database.

  • When you try to synchronize a scope that is currently being provisioned to a SQL Server or SQL Azure database, Microsoft.Synchronization.Data.DbProvisioningException is thrown.

c. Microsoft.Synchronization.Data.DbNotProvisionedException thrown when the database has not been provisioned

d. Microsoft.Synchronization.Data.DbPartiallyProvisionedException thrown when provisioning fails and cannot be rolled back

Microsoft.Synchronization.Data.DbPartiallyProvisionedException is thrown when certain failures occur while provisioning a SQL Azure database. This exception indicates that the provisioning transaction could not be rolled back, which leaves the database in an inconsistent state. To recover from this situation, catch this exception and deprovision the scope or template that was being provisioned by using the Microsoft.Synchronization.Data.SqlServer.SqlSyncScopeDeprovisioning class. After the scope or template has been deprovisioned, provisioning can be tried again. This exception wraps other exceptions that are thrown while provisioning a SQL Azure database. The original exception contains more detail about the error and can be found in the DbPartiallyProvisionedException.InnerException property.

Be aware that Microsoft.Synchronization.Data.DbPartiallyProvisionedException is erroneously referred to as Microsoft.Synchronization.Data.SqlServer.SqlSyncProvisioningException in the product documentation.

2. Database Synchronization

a. Use of batching can cause failure when destination provider uses Sync Framework 2.0

Synchronization fails if all of the following conditions are met:

  • Batching is used during synchronization.

  • The source provider uses Sync Framework 2.1.

  • The destination provider uses Sync Framework 2.0.

  • Both Sync Framework 2.0 and Sync Framework 2.1 are installed on the destination computer.

When all of these conditions are met, the destination provider throws InvalidCastException when it tries to deserialize the batch file. This occurs because the BinaryFormatter class that is used to deserialize the batch file detects the version of the assembly that produced the batch file. Therefore, when the batch file was produced by Sync Framework 2.1 components, the BinaryFormatter loads the Sync Framework 2.1 assembly to deserialize the batch file, but because the destination provider uses Sync Framework 2.0 components, the deserialized batch cannot be cast to the correct object and the exception occurs. This error occurs only if all of the above conditions are met. If only Sync Framework 2.0 is installed on the destination computer, synchronization functions correctly because the BinaryFormatter object loads the 2.0 assembly. If the source provider uses Sync Framework 2.0 and the destination provider uses Sync Framework 2.1, synchronization functions correctly because the 2.1 provider contains code that ensures that the correct assembly is loaded by the BinaryFormatter object.

To fix this problem without recompiling your application, you can use assembly redirection to load the correct assembly in your destination provider. To use assembly redirection, include an application configuration (AppName.exe.config) file in the same folder as the managed application executable. The following example shows the entry to add to your AppName.exe.config file.

 
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Synchronization.Data"
publicKeyToken="89845dcd8080cc91"
culture="neutral" />
<bindingRedirect oldVersion="2.1.0.0"
newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

3. Breaking Changes and Obsolete Members

The following breaking changes occurred between Sync Framework 2.0 and Sync Framework 2.1.

  • The database provider classes in the Microsoft.Synchronization.Data.SqlServerCe namespace require SQL Server Compact 3.5 SP2. Sync Framework methods that connect to a SQL Server Compact database throw an exception when an invalid version of SQL Server Compact is installed. If you have an existing database that synchronizes with an earlier version of Sync Framework, when you upgrade Sync Framework and SQL Server Compact and connect to the database by using a Sync Framework method, your database is automatically updated. For more information, see Upgrading SQL Server Compact in the product documentation.

  • The default option for creating tables and procedures when provisioning a SQL Server database by using a Microsoft.Synchronization.Data.SqlServer.SqlSyncScopeProvisioning object has changed from DbSyncCreationOption.Create to DbSyncCreationOption.CreateOrUseExisting. When you provision a database without specifying new values for the creation options, tables and procedures are created if they do not already exist in the database.

  • The Microsoft.Synchronization.Data.SqlServerCe.SqlCeSyncProviderAdapterConfiguration.QuotedTrackingTableName property has been removed because the Microsoft.Synchronization.Data.SqlServerCe.SqlCeSyncProviderAdapterConfiguration.TrackingTableName property has been changed to contain the same information.

  • Itanium-based systems are no longer supported and installation packages have not been released for this platform.

The following members are obsolete and should not be used in new development. They continue to function as expected in Sync Framework 2.1, but might be removed in a later version.

  • Constructors for the Microsoft.Synchronization.Data.SqlServer.SqlSyncScopeProvisioning class that do not have a SqlConnection parameter: SqlSyncScopeProvisioning() and SqlSyncScopeProvisioning.(DbSyncScopeDescription). Instead, use a constructor with a SqlConnection parameter, such as SqlSyncScopeProvisioning(SqlConnection). Also, be aware that when you use an obsolete version of this constructor, Sync Framework assumes a database edition of SQL Server 2005 and disables the use of bulk procedures for insert, update, and delete.

  • Methods of the Microsoft.Synchronization.Data.SqlServer.SqlSyncScopeProvisioning class that have a SqlConnection or database name parameter: SqlSyncScopeProvisioning.Apply(SqlConnection), SqlSyncScopeProvisioning.ScopeExists(SqlConnection), and SqlSyncScopeProvisioning.Script(String). Instead, set the connection in the SqlSyncScopeProvisioning constructor and use the methods without the connection parameter: SqlSyncScopeProvisioning.Apply(), SqlSyncScopeProvisioning.ScopeExists(String), and SqlSyncScopeProvisioning.Script().

  • Constructors for the Microsoft.Synchronization.Data.SqlServerCe.SqlCeSyncScopeProvisioning class that do not have a SqlCeConnection parameter: SqlCeSyncScopeProvisioning() and SqlCeSyncScopeProvisioning(DbSyncScopeDescription). Instead, use a constructor with a SqlCeConnection parameter, such as SqlCeSyncScopeProvisioning(SqlCeConnection).

  • Methods of the Microsoft.Synchronization.Data.SqlServerCe.SqlCeSyncScopeProvisioning class that have a SqlCeConnection parameter: SqlCeSyncScopeProvisioning.Apply(SqlCeConnection) and SqlCeSyncScopeProvisioning.ScopeExists(String, SqlCeConnection). Instead, set the connection in the SqlCeSyncScopeProvisioning constructor and use the methods without the connection parameter: SqlCeSyncScopeProvisioning.Apply() and SqlCeSyncScopeProvisioning.ScopeExists(String).