微软BI 之SSIS 系列 - 在 SSIS Script 中读写用户自定义变量与断点调试

浏览: 6441

开篇介绍

在 ETL 的设计与开发过程中,我们经常需要通过一些编程的方式来解决一些比较复杂的需求,比如通过 C# 的代码来完成一些复杂逻辑的操作。那么在 SSIS 中有两个基本的控件可以让我们通过 C# 或者 VB 的语法进行自定义编程,一个是控制流中的 Script Task ,一个是数据流中的 Script Component。如果要学习和掌握 Script Component,那么首先就应该来学习 Script Task,并掌握例如如何进行包变量的读写操作,断掉调试等基本操作。

Script Task 中的变量读写操作

新建一个包并拖放一个 Script Task 到控制流中,并新建以下变量,注意它们的数据类型。

我们要做的事情是,在 Script Task 中将通过系统变量启动时间给 PV_CURRENT_DATE 来赋值。并且 PV_YEAR, PV_MONTH,PV_DAY 的值均来自于对系统时间的解析,而 PV_PACKAGE_NAME 则取自系统变量包的名称。

在这里首先选择 C# 或者 VB 的编程方式,这个选择取决于大家对这两种编程方式的熟悉程度,对于我来说 C# 的熟悉程度要高于 VB 一些,所以会选择 C#,这也是 SQL Server 2008 以后才有的支持。

  1. ReadOnlyVariables - 这些变量是只读的,也就是说在编辑 Script Task 的时候不能给变量来赋值。
  2. ReadOnlyWriteVariables - 这些变量是可读可写的,在编辑代码的时候可以给它们来赋值。

在 ReadOnlyVariables 中选择系统变量,只读属性。

在选择 ReadWriteVariables 时会发现只有用户自定义的变量是可以被选择的,这也就说明系统变量是只读的。

选择完变量之后的效果,并编辑 Script。

在第一次打开的时候会比较慢,后面就会快一些。

Main 方法中的代码 

在 Script Task 中,如果需要使用到一些类,比如像 IO 操作的类,那么需要在命名空间中去引用它,下面是几种默认的引用。

先获取两个系统变量的值保存在两个变量中,注意 CurrentDate 的类型是 DateTime 类型,它在接受系统变量 StartTime 的时候是需要强制类型转换将 .Value 表示的 Object 类型转换成 DateTime 类型的。其次再使用两个变量给用户自定义变量赋值,最后使用 MessageBox 进行值的显示操作。

public void Main()
{
// TODO: Add your code here
// System::PackageName,System::StartTime
// User::PV_CURRENT_DATE,User::PV_DAY,User::PV_MONTH,User::PV_PACKAGE_NAME,User::PV_YEAR
// System Variables
String PackageName = Dts.Variables["System::PackageName"].Value.ToString();
DateTime CurrentDate
= (DateTime)Dts.Variables["System::StartTime"].Value;

// User Defined Variables
Dts.Variables["User::PV_CURRENT_DATE"].Value = CurrentDate;
Dts.Variables[
"User::PV_YEAR"].Value = CurrentDate.Year;
Dts.Variables[
"User::PV_MONTH"].Value = CurrentDate.Month;
Dts.Variables[
"User::PV_DAY"].Value = CurrentDate.Day;
Dts.Variables[
"User::PV_PACKAGE_NAME"].Value = PackageName;

String VarMessage
= "Package Name - " + Dts.Variables["User::PV_PACKAGE_NAME"].Value + "\n"+
"Current Date - " + ((DateTime)Dts.Variables["User::PV_CURRENT_DATE"].Value).ToLongDateString() + "\n"+
"Year - " + Dts.Variables["User::PV_YEAR"].Value + "\n"+
"Month - " + Dts.Variables["User::PV_MONTH"].Value + "\n"+
"Day- " + Dts.Variables["User::PV_DAY"].Value;

MessageBox.Show(VarMessage);

Dts.TaskResult
= (int)ScriptResults.Success;
}

保存并执行包的效果 - 

常见错误举例说明与断点调试

第一 - 丢失变量

在选择变量的时候,少选了变量,这样在代码中使用到这个变量就会报错。

运行时错误 -

也很难从这个错误信息中获取非常有价值的信息。

打开 Script 并在合适的位置放置断点 - BreakPoint。

将本包设置为项目的启动项。

点击进行断点执行和调试。

当包中有很多 Task 的时候,执行到这个 Task 的时候就会进入代码内部。

按 F10 逐过程或者F11 逐句单步调试的时候,会看到错误发生的地方。第一句提示我们的错误就是:

The element cannot be found in a collection。This error happens when you try to retrieve an element from a collection on a container during execution of the package and the element is not there.

不能在集合中找到这个元素,这个错误通常发生在包运行期间试图从容器中的集合里获取元素的时候那个元素却找不到了。

通过这种方式我们就可以知道我们的错误发生在哪里了,就可以很快的修复这个错误。

第二 - 给只读变量赋值

给 PV_CURRENT_DATE 只读状态,不能赋值。

按道理包在运行的时候会发生失败,但是最终包还是成功运行的!这里是微软 SSIS 2012 版本的一个 Bug,这个例子在 SQL Server 2008 R2 版本上会出现错误。

那么在 SSIS 2012 中要如何解决或者描述这个问题呢? 测试一下,修改变量 PV_CURRENT_DATE 将它的 ReadOnly 属性修改为 True,标明是只读,这个时候才会出错。

通过断点调试就会发现这个错误的原因就是 : Error trying to write to a read-only variables,试图向只读的变量写值。

总结

这个 Bug 的发现也是非常偶然的,因为按照在 2008 R2 对这个控件的用法是没有问题的,按照使用习惯也是不会发现这个问题的。正好是在演示 ReadOnly 的变量不能赋值的时候才发现这个地方是有问题的,这个 Bug 还是非常明显的,我也就这个问题提到官网论坛去了。

Is it a bug - SSIS 2012 ReadOnlyVariables in Script Task doesn't work

推荐 0
本文由 BIWORK 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册