我有一个正在 Visual Studio 2022 中开发的针对 SQL Server 2019 的 SSIS 包,但我遇到了一个奇怪的问题。
我有一个刷新不记名令牌的数据流,这意味着它从数据库检索令牌,检查过期时间,如果过期,则刷新它,如果未过期,则重用数据库中的令牌。然后,它将该令牌存储在包范围变量中,以便稍后在其他数据流中使用。
要更新令牌或重用令牌,我使用两个不同的脚本组件,它们通过使用以下表达式的条件拆分进行路由:
HasExpired == TRUE
HasExpired == FALSE
我遇到的问题是:我的令牌没有过期,但由于某种原因,负责更新过期令牌的脚本组件中的
void PostExecute()
被触发。我做了很多测试,似乎有时当我重新启动 VS 时它会起作用,但在运行几次后它又开始这样做了。
知道可能是什么原因造成的吗?
我尝试在脚本组件中设置断点,但错误的方法仍然不断触发。我还尝试启用数据查看器,数据查看器显示正确的数据,但仍然会触发错误的
PostExecute()
。
您可以构建一个简单的复制品,它确实显示条件分割可能正在做它应该做的事情
在这里,我生成 2 行,并将该位设置为 true 和 false,并看到正确的路径亮起。然后我将 False 行和零行路由到 Row Count 组件,它会像脚本组件一样获得绿色复选标记
如果您查看输出,您会看到一行内容
信息:DFT 演示中的 0x0,过期路径的执行后:RowsReceived = False
虽然您没有显示 PostExecute 的代码,但我愿意发布带有经过教育的猜测的答案。无论是否有任何数据点亮组件,PostExecute 事件每次都会触发。这在 SSIS 中很常见,因为它需要在自身之后进行清理,因此脚本组件中的逻辑每次都会触发,除非您告诉它不要这样做。
在下面的脚本任务中,我声明一个名为
rowsReceived
的成员变量并将其初始化为 False。
在我的 PostExecute 方法中,我向输出日志写入两次。第一条是您在我的屏幕截图中看到的消息。第二个位于 If 块内,仅当该行实际落在组件中时才会触发。
最后也是最琐碎的部分是 ProcessInputRows 方法。无论是 1 行还是 10 亿行,它们都会进行相同的评估,因为它们将我们的
rowsReceived
从 False 翻转为 True。
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
bool rowsReceived;
public override void PreExecute()
{
base.PreExecute();
rowsReceived = false;
}
public override void PostExecute()
{
base.PostExecute();
bool fireAgain = false;
ComponentMetaData.FireInformation(0, "PostExecute of Expired path", string.Format("RowsReceived = {0}", rowsReceived), "", 0, ref fireAgain);
if (rowsReceived)
{
ComponentMetaData.FireInformation(0, "PostExecute of Expired path", "DO TASK HERE TO REFRESH TOKENS", "", 0, ref fireAgain);
}
}
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
rowsReceived = true;
}
}
将我的源查询切换回 1 false、1 true,您可以看到输出日志中显示一条新消息,该消息对应于您将在其中执行令牌刷新活动的占位符。
有道理吗?