为什么SSIS脚本任务无法评估表达式?

时间:2013-02-25 17:36:07

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

SSIS脚本任务错误

我有一个包含目录和文件名的表,然后我想用它作为文本文件的连接字符串。

我使用foreach循环来获取分配给变量的表中的值,而不是我有一个表达式变量,它是源Dir +源文件名的组合,因为没有其他方法可以检查文件是否存在在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()在脚本中放了一块手表,我得到了功能评估超时。

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

为什么表达式无法在脚本任务中正确评估?有人如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

可能的选择:

您可以使用 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

Control Flow tab

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

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

Variables

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

SELECT srcPath, srcName FROM dbo.FileNames

Execute SQL Task - General

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

Execute SQL Task - Result Set

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

Foreach Loop Container - Collection

配置两个包变量以存储列值,因为结果集正在循环。

Foreach Loop Container - Variable Mappings

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

Script Task Editor

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

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
    }
}

Script Task Code

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

Package Execution

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

Package Failure

对OP评论的回应:

  

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

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

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

答案 1 :(得分:1)

对于初学者,我会在调用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;
    }
}

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

答案 2 :(得分:-1)

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