我有一个包含目录和文件名的表,然后我想用它作为文本文件的连接字符串。
我使用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,这就是脚本组件无法评估它的原因......
为什么表达式无法在脚本任务中正确评估?有人如何解决这个问题?
答案 0 :(得分:2)
您可以使用 Execute SQL Task
来获取记录集,而不是使用 Data Flow Task
。
让我们假设您的数据库中有一个名为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
创建以下变量。建议在变量 @[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
查询返回的结果集应存储在数据类型 FileNames
的变量 Object
中。
使用 Foreach Loop Container
配置 Foreach ADO Enumerator
以读取变量 FileNames 。
配置两个包变量以存储列值,因为结果集正在循环。
配置脚本任务编辑器以读取变量 srcFull
将以下代码添加到脚本任务中。
#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
不存在。
我做了你在这里给我看的东西,似乎我的问题是因为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