如何使 SSIS 脚本任务失败(使用 C#,2008)
Posted
技术标签:
【中文标题】如何使 SSIS 脚本任务失败(使用 C#,2008)【英文标题】:How to fail a SSIS Script Task (using C#, 2008) 【发布时间】:2014-09-04 16:11:32 【问题描述】:我见过很多代码,但显然它们无济于事。
这是我必须遵循的逻辑:
我正在读取一个包含金额字段的文件。此金额字段可以有负数。如果我在文件中发现负数,我必须移动文件并使包失败。
到目前为止我做了什么:
添加了一个脚本任务来获取文件路径,添加了循环来读取该路径中的所有文件,在循环内部(添加了一个 DTS 任务来将负数的成员移动到记录集,添加了脚本任务来检查是否有任何记录集中的行,如果 count > 0 则脚本任务失败,因此包失败,否则通过)
scipt 任务的代码:
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
using System.Data.OleDb;
using System.IO;
using System.Xml;
// name space call here etc, etc..
enum ScriptResults
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
;
public void Main()
// TODO: Add your code here
bool fireAgain = true;
DataTable dtable = new DataTable();
OleDbDataAdapter da = new OleDbDataAdapter();
// Setting this incase there are multiple files being checked
Dts.Variables["InvalidFile"].Value = "False";
da.Fill(dtable, Dts.Variables["NegativeAmountMember"].Value);
// I do get my desired result here of 1
Dts.Events.FireInformation(0, "dtable", dtable.Rows.Count.ToString(), String.Empty, 0, ref fireAgain);
if (dtable.Rows.Count > 0)
Dts.Variables["InvalidFile"].Value = "True";
Dts.Events.FireInformation(0, "InvalidFile", Dts.Variables["InvalidFile"].Value.ToString(), String.Empty, 0, ref fireAgain); // This does get displayed but, nothing happens after this step.
Dts.TaskResult = (int)ScriptResults.Failure; // this method never technically executes
return; // added this because someone somewhere said in a post to do so
else
Dts.TaskResult = (int)ScriptResults.Success;
我一切正常,除了这个脚本任务失败。
我也尝试过 FireError,即使它没有被调用。
发生了什么,谁能解释一下?
【问题讨论】:
我不明白你对Dts.TaskResult = (int)ScriptResults.Failure;
的评论这任务失败了。帮助我了解为什么不会发生这种情况
@billinkc 我有执行的火灾信息事件,但是当执行Dts.TaskResult = (int)ScriptResults.Failure;
步骤时,ScriptTask 永远不会停止/失败。它仍处于“黄色阶段”。
我认为您需要根据您的要求将Script Task
属性ForcedParentOnFailure
或ForcedPackageOnFailure
设置为True。你有一个循环容器中的任务。
@t_m FailParentOnFailure 和 FailPackageOnFailure 均设置为 true。但是,问题是代码中的死锁。已发布答案。
【参考方案1】:
在 SSIS 中,失败不会自动停止执行(如您所见)。失败是一种状态,表示出现了问题。执行不会在失败时突然停止这一事实使您可以精心安排错误处理。例如,您可能希望在发生故障时执行补救措施。
您问题中的以下代码片段将任务的结果设置为失败(第 1 行)并结束任务的执行(第 2 行)。
Dts.TaskResult = (int)ScriptResults.Failure;
return;
如果任务没有失败/执行没有停止,那么问题几乎肯定与控制上述代码是否执行的if
条件有关(if (dtable.Rows.Count > 0)
)——不知何故,这个条件没有评估当你期望它为真时。
脚本任务也有可能失败但看起来不像。可能发生的情况是脚本任务遇到错误并失败,然后循环开始新的迭代并为下一次迭代运行脚本任务。快速失败 -> 下一次迭代 -> 下一个脚本任务执行可能会使脚本任务在失败后看起来像处于运行状态。
如果您希望脚本任务无法阻止循环进一步迭代,您将需要以某种方式将 循环的 ExecutionResult
切换为失败。您可以通过设置脚本任务FailParentOnFailure
或将循环的MaximumErrorCount
属性设置得足够低,以便脚本任务失败引发的错误导致循环的MaximumErrorCount
阈值得到满足。
【讨论】:
【参考方案2】:伙计们,我发现了问题所在。问题是带有 InvalidFile 变量的代码中的死锁。
添加:
Variables lockedVariables = null;
Dts.VariableDispenser.LockOneForWrite("InvalidFile", ref lockedVariables);
lockedVariables["InvalidFile"].Value = "True";
lockedVariables.Unlock();
到代码,问题现在消失了。关于@Ben Gribaudo 对无效循环的评论,循环是有效的,我在代码中的 cmets 建议这样。
deadlocked 变量也被用于发送电子邮件的 onError 任务中。由于变量被锁定在循环中以进行写入,并且脚本任务在 onError 完成之前从未真正失败,因此变量保持锁定状态。添加lock for one write
代码后,一切正常。
感谢您的帮助、解释和回答。
【讨论】:
【参考方案3】:正是我要查找的内容,如果对 SPROC 的特定调用在我的捕获中返回 SQL 错误,则退出。
catch (SqlException ex)
ExceptionLogging.SendExcepToDB(ex);
Dts.TaskResult = (int)ScriptResults.Failure;
return;
【讨论】:
【参考方案4】:我没有足够好的“声誉”,所以我必须发布答案...... 锁定变量将阻止您失败的事件处理程序工作!
因此,在脚本组件失败之前,释放变量是一个很好的做法。
在 catch 语句中解锁所有代码的更直接的代码:
Dts.Variables.Unlock();
无需建立新的变量对象来解锁它们。
【讨论】:
即使您不认为,这也是一个答案,即使它很短。 ;-)以上是关于如何使 SSIS 脚本任务失败(使用 C#,2008)的主要内容,如果未能解决你的问题,请参考以下文章