1

在 Sql Server 2008 中设置复制时,系统会在每个复制的表上创建触发器,以便于将数据传输到订阅数据库。

SET NOCOUNT ON系统生成的触发器用于防止其操作影响函数值是否是预期的行为@@ROWCOUNT

背景

我将 NHibernate 与 Sql Server 2008 后端数据库一起使用。数据库启用了复制,它在已发布的表上创建系统生成的触发器,以方便将数据传输到订阅者。

没有复制一切正常,但复制 NHibernate 的行受影响的验证检查失败。除了受命令本身影响的行之外,ADO.Net 所说的受影响的行数似乎还包括受关联触发器影响的行。

在最初的问题中,我提到了@@ROWCOUNTSql Server 函数,但我真正的意思是 ADO.NetExecuteNonQuery方法返回的“受影响的行”值。我想我是在假设后者是由前者喂养的(可能是错误的)。

作为临时解决方案,我们修改了复制触发器以SET NOCOUNT ON在任何更新之前添加,并在任何更新完成后将其撤消。这暂时解决了我们的问题,但不是一个可行的永久解决方案。根据我们收到的建议和常识,不建议编辑系统触发器。

然而,这确实向我表明我们已经确定了确切的问题。受触发器影响的行将包含在当前命令的最终受影响行数中。NHibernate 预计只有已知数量的行会受到影响,它不会为任何未知的(就 NHibernate 而言)触发器添加到此计数。

我们目前正在研究涉及扩展 NHibernate 以添加处理或至少抑制此问题的能力的选项。我们的资源包括这个 SO question

我还发现这篇文章似乎暗示系统生成的触发器默认情况下已经将 NOCOUNT 选项设置为 ON,从而无需修改它们。这对我们来说绝对不是这样,所以我想知道为什么会这样。

  1. 系统生成的触发器的默认情况是什么?
  2. 行为是否可配置?
  3. 它是否取决于复制的类型——合并、事务?
4

1 回答 1

1

我无法确定原始问题的答案 - (应该/可以/如何)Sql Server 系统生成的复制触发器自动包含 SET NOCOUNT ON 选项。

我们的 DBA 团队认为答案是否定的。他们还说(非常正确)他们不会在生产中自定义系统触发器。

对我开放的选项是...

  1. 修改/扩展 NHibernate 以TooManyRowsAffectedException在检测到行计数不匹配时不抛出。
  2. 淘汰 NHibernate 并替换为存储过程和手动映射到业务对象。

我们选择了选项 1。

我的解决方案是通过以下方式修改 NHibernate (2.1) Core ...

  1. 首先,我添加了一个新的配置选项来控制我的新行为。
  2. VerifyOutcomeNonBatched然后我修改了类中的和VerifyOutcomeBatched方法的签名,NHibernate.AdoNet.Expectations以接受新的配置值作为参数。这涉及修改调用这些方法的几个地方。
  3. 最后,我修改了这两种方法,以便它们TooManyRowsAffectedException根据配置选项分别抛出/抑制。

我会对任何建议的替代实现感兴趣。

于 2010-12-10T11:21:14.100 回答