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

标签 c# synchronization sync microsoft-sync-framework

我使用的是 Microsoft sync framework 2.1 版本

我们正在尝试实现数据库版本控制,即如果服务器数据库中的表架构发生变化,所有或某些客户端应该仍然能够同步他们的数据,而无需进行相同的架构更改或不采用更新的数据库。 在更高级别,我们需要为具有相同服务器数据库的不同客户端维护多个应用程序版本。

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

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

最佳答案

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

可能的解决方案

如果我理解您的意思,您希望一个范围或模板具有多个预配配置。

你的范围:

  • (版本 1)
    • 表 1(A 列,B 列)
  • (版本 2)
    • 表 1(列 A、列 B、新列 C)
    • NewTable2(ColumnX、ColumnY、ColumnZ)

在我看来最好使用:

Version1_YourScope:

  • 表 1(A 列,B 列)

Version2_YourScope:

  • 表 1(列 A、列 B、新列 C)
  • NewTable2(ColumnX Columny ColumnZ)

所以在这种情况下,您不必处理内部 Sync Framework 过程的版本,现在您需要通过为正确的客户端提供正确的权限来处理外部的版本一组范围。

做什么:

此更改需要在配置期间进行一些更改。范围相互重叠会带来一些问题:

  • 您必须为 Table1 设置两个 BulkType(1 个没有 NewColumnC 和 1 个包含这个新列的类型)
  • 您必须对表 1 进行两项选择更改
  • Table1 必须有两个 BulkInsert 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:获取配置脚本

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声明。您需要执行两个 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
}

6:确保老客户提供 Version1_YourScope,新客户提供Version2_YourScope,这样客户端在多个版本之间没有重叠。

如果您因为要传递过滤器参数而使用模板,则需要注意以下事项:

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

祝你好运!

关于c# - 如何将参数传递给 Microsoft Sync 2.1 生成的存储过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16738621/

相关文章:

google-chrome - 如何使用 Chrome 同步 XMPP 服务器进行身份验证?

Android(相机)- 如何将 stopPreview() 与 onPictureTaken() 同步?

c# - 使用 asp.net Identity 进行 Azure AD 身份验证以进行授权

c# - InputBinding 和 WebBrowser 控件

java - 总是同一个线程获得 CPU 时间

javascript - 保持 JavaScript 和 CSS 同步的做法?

linux - rsync不删除

c# - 数组声明中有逗号是什么意思?例如漂浮[,]

c# - 创建子进程 C# win32 API

c# - 在 C# 中监视与互斥锁