Bat*_*eni 7 c# synchronization sync microsoft-sync-framework
我正在使用Microsoft同步框架2.1版本
我们正在尝试实现数据库版本控制,即如果服务器数据库中存在表模式更改,则所有或某些客户端仍应能够同步其数据而无需执行相同的模式更改或不使用更新的数据库.在更高级别,我们需要为具有相同服务器DB的不同客户端维护多个应用程序版本.
我试图将应用程序版本作为参数传递给所有存储过程,以便我可以处理多个客户端的数据版本.我能够将参数传递给"select_chagnes"存储过程..但我的问题是如何将版本号传递给所有同步生成的存储过程,以便在所有同步生成的过程中生成参数@version.
要么
欢迎任何维护客户特定数据的建议我们的主要目标是允许现有客户端同步其数据库,而无需更新最新的数据库.这样我们客户端就可以拥有多个指向同一服务器数据库的应用程序版本.
备注如果您删除旧客户端配置的列或表,我的解决方案将不起作用。如果你想删除列,你需要执行多个阶段。首先将所有人升级到版本 1。如果所有客户端都升级,您可以删除列和表。
如果我很了解您,您希望拥有一个具有多个预配置配置的范围或模板。
您的范围:
在我看来,最好使用:
版本1_您的范围:
版本2_您的范围:
因此,在这种情况下,您不必处理Sync Framework 过程内部的版本,现在您需要通过为正确的客户端提供正确的范围集来处理外部版本。
此更改需要在配置期间进行一些更改。范围相互重叠会带来一些问题:
在配置期间您可能会使用SqlSyncScopeProvider.Apply(). 还有一个返回脚本而不是应用脚本的函数:SqlSyncScopeProvider.Script()。这将返回配置脚本。
所以你可以这样做:
1:使用以下配置设置使重叠范围成为可能:
_scopeProvisioning.SetCreateProceduresForAdditionalScopeDefault(DbSyncCreationOption.Create);
_scopeProvisioning.SetCreateTableDefault(DbSyncCreationOption.Skip);
_scopeProvisioning.SetCreateProceduresDefault(DbSyncCreationOption.CreateOrUseExisting);
_scopeProvisioning.SetCreateTrackingTableDefault(DbSyncCreationOption.CreateOrUseExisting);
_scopeProvisioning.SetCreateTriggersDefault(DbSyncCreationOption.CreateOrUseExisting);
Run Code Online (Sandbox Code Playgroud)
2:获取配置脚本
var builder = new StringBuilder(_scopeProvisioning.Script());
Run Code Online (Sandbox Code Playgroud)
3:将每个表重命名<tablename>_<procedure/bulktype>为<scopename>_<tablename>_<procedure/bulktype>
// Rename <tablename>_selectchanges to <scopename>_<tablename>_selectchanges and also all other stored procedures and bulk type
builder = builder.Replace(String.Format("CREATE PROCEDURE [{0}_selectchanges", table.Name), String.Format("CREATE PROCEDURE [sync].[{1}_{0}_selectchanges", table.Name, scope.Name));
builder = builder.Replace(String.Format("SelChngProc=\"[{0}_selectchanges", table.Name), String.Format("SelChngProc=\"[sync].[{1}_{0}_selectchanges", table.Name, scope.Name));
builder = builder.Replace(String.Format("[{0}_BulkType]", table.Name), String.Format("[{1}_{0}_BulkType]", table.Name, scope.Name));
builder = builder.Replace(String.Format("[{0}_selectrow]", table.Name), String.Format("[{1}_{0}_selectrow]", table.Name, scope.Name));
builder = builder.Replace(String.Format("[{0}_insert]", table.Name), String.Format("[{1}_{0}_insert]", table.Name, scope.Name));
builder = builder.Replace(String.Format("[{0}_update]", table.Name), String.Format("[{1}_{0}_update]", table.Name, scope.Name));
builder = builder.Replace(String.Format("[{0}_delete]", table.Name), String.Format("[{1}_{0}_delete]", table.Name, scope.Name));
builder = builder.Replace(String.Format("[{0}_insertmetadata]", table.Name), String.Format("[{1}_{0}_insertmetadata]", table.Name, scope.Name));
builder = builder.Replace(String.Format("[{0}_updatemetadata]", table.Name), String.Format("[{1}_{0}_updatemetadata]", table.Name, scope.Name));
builder = builder.Replace(String.Format("[{0}_deletemetadata]", table.Name), String.Format("[{1}_{0}_deletemetadata]", table.Name, scope.Name));
builder = builder.Replace(String.Format("[{0}_bulkinsert]", table.Name), String.Format("[{1}_{0}_bulkinsert]", table.Name, scope.Name));
builder = builder.Replace(String.Format("[{0}_bulkupdate]", table.Name), String.Format("[{1}_{0}_bulkupdate]", table.Name, scope.Name));
builder = builder.Replace(String.Format("[{0}_bulkdelete]", table.Name), String.Format("[{1}_{0}_bulkdelete]", table.Name, scope.Name));
Run Code Online (Sandbox Code Playgroud)
4:对于与现有范围重叠的每个表,将 CREATE TRIGGER 更改为 ALTER TRIGGER,因为它们已存在于数据库中
builder = builder.Replace(String.Format("CREATE TRIGGER [{0}_insert_trigger]", table.Name), String.Format("ALTER TRIGGER [{0}_insert_trigger]", table.Name));
builder = builder.Replace(String.Format("CREATE TRIGGER [{0}_update_trigger]", table.Name), String.Format("ALTER TRIGGER [{0}_update_trigger]", table.Name));
builder = builder.Replace(String.Format("CREATE TRIGGER [{0}_delete_trigger]", table.Name), String.Format("ALTER TRIGGER [{0}_delete_trigger]", table.Name));
Run Code Online (Sandbox Code Playgroud)
5:执行新脚本。请注意,该脚本包含很多GO语句。您需要GO在一个 SqlCommand 中执行两个之间的所有内容。
string[] seperatedScript = GetProvisionScriptSplittedOnGOstatement(builder.ToString);
foreach(string command in seperatedScript)
{
new SqlCommand(command, connection).ExecuteNonQuery();
// make sure you dispose SqlCommand correctly. Not in this example
}
Run Code Online (Sandbox Code Playgroud)
6:确保旧客户端仅提供Version1_YourScope,新客户端仅提供 Version2_YourScope,以便客户端多个版本之间不会重叠。
如果您因为想要传递过滤器参数而使用模板,则需要注意以下事项:
祝你好运!