0

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()我得到并且函数评估超时。

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

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

4

3 回答 3

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以读取表数据并将其存储在对象数据类型中。将 aForeach Loop Container放在 Execute SQL Task 之后,并将 aScript Task放在Foreach 循环容器中

控制流选项卡

创建以下变量。建议@[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

变量

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

SELECT srcPath, srcName FROM dbo.FileNames

执行 SQL 任务 - 常规

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

执行 SQL 任务 - 结果集

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

Foreach 循环容器 - 集合

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

Foreach 循环容器 - 变量映射

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

脚本任务编辑器

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

用于 SSIS 2008 及更高版本的 C# 脚本任务代码:

#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

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

于 2013-02-25T18:21:06.163 回答
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;
    }
}

此处的目的是更好地了解失败记录的外观。

于 2013-02-25T18:19:22.563 回答
-1

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

于 2013-08-06T18:46:26.783 回答