如何将参数传递给Microsoft Sync 2.1生成的存储过程

本文关键字:1生 存储过程 Sync Microsoft 参数传递 | 更新日期: 2023-09-27 18:15:27

我使用的是Microsoft sync framework 2.1版本

我们正在尝试实现数据库版本控制,即如果在服务器数据库中有一个表模式更改,所有或一些客户端应该仍然能够同步他们的数据,而不需要做相同的模式更改或不采取更新的数据库。在更高的层次上,我们需要为具有相同服务器DB的不同客户端维护多个应用程序版本。

我试图将应用程序版本作为参数传递给所有存储过程,以便我可以处理多个客户端的数据版本。我能够传递参数到"select_changes"存储过程..但是我的问题是如何将版本号传递给所有同步生成的存储过程,以便在所有同步生成的过程中生成参数@version。

任何维护客户端特定数据的建议都是受欢迎的,我们的主要目标是允许现有的客户端同步他们的数据库,而不需要最新的数据库更改。因此,我们可以客户端可以有多个应用程序版本指向同一个服务器数据库。

如何将参数传递给Microsoft Sync 2.1生成的存储过程

Remark如果您删除旧客户端提供的列或表,我的解决方案将不起作用。如果你想删除列,你需要做的是多个阶段。首先将所有人升级到版本1。如果所有客户端都升级了,可以删除列和表。

可能的解决方案

如果我没理解错的话,你是想让一个作用域或模板有多个配置。

YourScope:

  • (Version1)
    • 表1(一列圆柱,ColumnB)
  • (Version2)
    • Table1(ColumnA, ColumnB, newcolumn )
    • NewTable2(ColumnX, ColumnY, ColumnZ)

我认为用

Version1_YourScope:

  • 表1(一列圆柱,ColumnB)

Version2_YourScope:

  • Table1(ColumnA, ColumnB, newcolumn )
  • NewTable2(ColumnX column ColumnZ)

所以在这种情况下,你不必处理同步框架过程中的版本,现在你需要通过给正确的客户端正确的作用域集来处理外部的版本

怎么做:

此更改需要在配置期间进行一些更改。作用域相互重叠会产生一些问题:

  • 你必须有两个BulkTypes为表1(1不带 newcolumn 和1类型有这个新列在内)
  • 表1
  • 必须有两个Select Changes
  • 必须为Table1
  • 设置两个bulkinset sp
  • 你只需要为Table1
  • 设置一组触发器
  • 你想只有一个跟踪表的Table1

在配置期间,您可能使用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);

2: Get provision script

var builder = new StringBuilder(_scopeProvisioning.Script());

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));

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));

5:执行新脚本。注意,该脚本包含许多GO语句。您需要在一个SqlCommand中执行两个GO之间的所有内容。

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
}

6:确保旧客户端规定 Version1_YourScope和新客户端规定Version2_YourScope,以便客户端多个版本之间没有重叠。

如果你正在使用模板,因为你想要传递过滤器参数,你需要注意以下事情:

  • 在多个作用域中提到的表的不同过滤列会导致问题,因为触发器不知道使用多个过滤列的多个作用域
  • 配置一个新的过滤列需要在已经存在的跟踪表中添加一个新列

祝你好运!