【问题标题】:Why does the SSIS Script Task fail to evaluate an expression?为什么 SSIS 脚本任务无法计算表达式?
【发布时间】:2013-02-25 17:36:06
【问题描述】:

SSIS 脚本任务错误

我有一个包含目录和文件名的表,然后我想将其用作到/来自文本文件的连接字符串。

我使用 foreach 循环从分配给变量的表中获取值,而不是我有一个表达式变量,它是源目录 + 源文件名的组合,因为没有其他方法可以检查文件是否存在在 SSIS 中只有一个脚本任务,我这样做了

public void chkIfExist()
{
    if (File.Exists(Dts.Variables["User::srcFull"].Value.ToString()))
    {
        Dts.TaskResult = (int)ScriptResults.Success;    
    }
    else
    {
        Dts.TaskResult = (int)ScriptResults.Failure;
    }
}

注意:User::srcFull 是一个可验证的表达式@[User::srcPath] + @[User::srcFile]

它一直在我身上崩溃,所以我在运行时在脚本中放置了一个手表 Dts.Variables["User::srcFull"].Value.ToString() 并且我得到并且函数评估超时。

我试图弄清楚发生了什么,我得出的结论是,由于这些值来自原始集,这就是脚本组件无法评估它的原因......

为什么表达式无法在脚本任务中正确计算?有没有人可以解决这个问题?

【问题讨论】:

  • 我实际上使用数据流任务将数据获取到行集目标,是的,我使用 Foreach ADO 枚举器来读取变量,所以我在路径变量中获取路径和文件变量中的文件名。所以我需要验证文件是否存在于脚本组件中,所以我得到了另一个变量,它是路径和文件的组合,在那里我得到了评估超时
  • siva,我的问题不是脚本找不到文件,而是它无法评估Dts.Variables["User::srcFull"].Value.ToString()
  • 在表达式生成器中我没有收到任何错误,实际上现在是 ReadWriteVariables 有区别吗?
  • 我还尝试为User::srcFull 变量分配一个像 1+1 这样的常量表达式,它起作用了,唯一不起作用的时候是它来自表...

标签: c# sql-server ssis etl business-intelligence


【解决方案1】:

可能的选择:

您可以使用 Execute SQL Task 来获取记录集,而不是使用 Data Flow Task

SSIS 2012 包说明示例:

让我们假设您的数据数据库中有一个名为 dbo.FileNames 的表,其中包含一些示例行。

创建和填充表格脚本:

CREATE TABLE dbo.FileNames(
    srcPath nvarchar(255) NULL,
    srcName nvarchar(60) NULL
);

GO

INSERT INTO dbo.FileNames (srcPath, srcName) VALUES
        ('C:\temp', 'File_1.txt')
    ,   ('C:\temp', 'File_2.txt')
    ,   ('C:\temp', 'File_3.txt')
    ;
GO

配置 控制流 选项卡,如下所示。放置 Execute SQL Task 以读取表数据并将其存储在对象数据类型中。在执行 SQL 任务之后放置一个Foreach Loop Container,在 Foreach 循环容器中放置一个 Script Task

创建以下变量。建议在变量 srcFull 上使用表达式 @[User::srcPath] + "\\" + @[User::srcFile],这样如果路径缺少尾部反斜杠,则会在路径和文件名之间相应地添加。

Variable name  Scope         Data type  Expression
-------------- ------------- ---------- -----------
FileNames      SO_15072939   Object
srcFile        SO_15072939   String
srcFull        SO_15072939   String     @[User::srcPath] + "\\" + @[User::srcFile]
srcPath        SO_15072939   String

配置 Execute SQL Task 以针对连接管理器运行以下查询以读取文件路径和名称信息。

SELECT srcPath, srcName FROM dbo.FileNames

查询返回的结果集应该存储到数据类型为Object的变量FileNames中。

配置 Foreach Loop Container 以使用 Foreach ADO Enumerator 读取变量 FileNames

配置两个包变量以在循环遍历结果集时存储列值。

配置脚本任务编辑器以读取变量srcFull

将以下代码添加到脚本任务中。

在 C# 中为 SSIS 2008 及更高版本编写任务代码:

#region Namespaces
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
using System.IO;
#endregion

namespace ST_f1d7b6ab42e24ad5b5531684ecdcae87
{
    [Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
    public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
    {
        public void Main()
        {
            string filePath = Dts.Variables["User::srcFull"].Value.ToString();

            MessageBox.Show(filePath);

            Dts.TaskResult = File.Exists(filePath)
                                ? (int)ScriptResults.Success
                                : (int)ScriptResults.Failure;
        }

        #region ScriptResults declaration
        enum ScriptResults
        {
            Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
            Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
        };
        #endregion
    }
}

执行包会在MessageBox中显示变量值。

此示例中的包将失败,因为路径 C:\temp\File_1.txt 不存在。

回应 OP 的评论:

我做了你在这里展示给我的,似乎我的问题是因为 User::srcFile 变量作为 ReadWriteVariables 添加到脚本任务中(因为我需要在同一个脚本中用它做一些事情)它有点被锁定,所以定义为 @[User::srcPath] + @[User::srcFile] 的 User::srcFull 变量无法评估..

我在脚本任务编辑器上将变量srcFullReadOnlyVariables修改为ReadWriteVariables并且表达式仍然正确评估。我在示例输入中创建了这三个文件,并且包在消息框中正确显示了每个路径并成功完成了执行。

将变量 srcPathsrcFile 添加到脚本任务编辑器的 ReadWriteVariables 部分只会导致冲突因为现在 Script TaskForeach 循环容器 都在尝试更新相同的变量。

【讨论】:

  • 我做了你在这里展示给我的事情,似乎我的问题是因为User::srcFile 变量作为ReadWriteVariables 添加到脚本任务中(因为我需要做一些事情它在同一个脚本中)它有点被锁定,所以无法评估定义为 @[User::srcPath] + @[User::srcFile]User::srcFull 变量...
  • 尝试将srcFilesrcPath 作为ReadWriteVariables 添加到脚本任务中,如果您的脚本仍然有效,请告诉我...
  • 我为这个任务制作了一个不同的脚本,它似乎可以工作。
【解决方案2】:

对于初学者,我会在调用 File.Exists 之前使用所有三个变量引发信息事件:

public void chkIfExist()
{
    bool fireAgain = true;
    Dts.Events.FireInformation(0,
        "MyScriptTask",
        String.Format("srcPath is \"{0}\"", Dts.Variables["User::srcPath"].Value),
        "",
        0,
        ref fireAgain);
    Dts.Events.FireInformation(0,
        "MyScriptTask",
        String.Format("srcFile is \"{0}\"", Dts.Variables["User::srcFile"].Value),
        "",
        0,
        ref fireAgain);
    Dts.Events.FireInformation(0,
        "MyScriptTask",
        String.Format("srcFull is \"{0}\"", Dts.Variables["User::srcFull"].Value),
        "",
        0,
        ref fireAgain);
    string fullPath = Dts.Variables["User::srcFull"].Value.ToString();
    if (System.IO.File.Exists(fullPath))
    {
        Dts.TaskResult = (int)ScriptResults.Success;
    }
    else
    {
        Dts.TaskResult = (int)ScriptResults.Failure;
    }
}

这里的目的是更好地了解失败记录的样子。

【讨论】:

    【解决方案3】:

    您需要传递ReadOnlyVariables 部分中的所有变量,以便 scriptTask 评估它们。在你的情况下,我认为你的 ReadOnlyVariables 应该是srcPath, srcFile, srcFull

    【讨论】:

      猜你喜欢
      • 2012-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多