-2

我见过很多代码,但显然它们无济于事。

这是我必须遵循的逻辑:

我有一个正在读取的文件,其中有一个金额字段。此金额字段可以有负数。如果我在文件中发现负数,我必须移动文件并使包失败。

到目前为止我做了什么:

添加了一个脚本任务来获取文件路径,添加了循环来读取该路径中的所有文件,在循环内部(添加了一个 DTS 任务来将负数的成员移动到记录集,添加了脚本任务来检查是否有任何行在记录集,如果计数 > 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,即使它没有被调用。

这是怎么回事,谁能解释一下?

4

4 回答 4

4

在 SSIS 中,失败不会自动停止执行(如您所见)。失败是一种状态,表示出现了问题。执行不会在失败时突然停止这一事实使您可以精心安排错误处理。例如,您可能希望在发生故障时执行补救措施。

您问题中的以下代码片段将任务的结果设置为失败(第 1 行)并结束任务的执行(第 2 行)。

Dts.TaskResult = (int)ScriptResults.Failure;
return;

如果任务没有失败/执行没有停止,那么问题几乎肯定与if控制上述代码是否执行的条件有关(if (dtable.Rows.Count > 0))——不知何故,当你期望它时,这个条件没有评估为真。

脚本任务也有可能失败但看起来不像。可能发生的情况是脚本任务遇到错误并失败,然后循环开始新的迭代并为下一次迭代运行脚本任务。快速失败 -> 下一次迭代 -> 下一个脚本任务执行可能会使脚本任务在失败后看起来像处于运行状态。

如果您希望脚本任务无法阻止循环进一步迭代这一事实,您将需要以某种方式将循环 ExecutionResult切换为失败。您可以FailParentOnFailure通过设置脚本任务或将循环的MaximumErrorCount属性设置得足够低来做到这一点,以便脚本任务失败引发的错误会导致满足循环的MaximumErrorCount阈值。

于 2014-09-04T19:36:11.080 回答
0

伙计们,我发现了问题所在。问题是带有 InvalidFile 变量的代码中的死锁。

添加:

    Variables lockedVariables = null;
    Dts.VariableDispenser.LockOneForWrite("InvalidFile", ref lockedVariables);
    lockedVariables["InvalidFile"].Value = "True"; 
    lockedVariables.Unlock();

到代码,问题现在消失了。关于@Ben Gribaudo 对无效循环的评论,循环是有效的,我在代码中的评论表明了这一点。

deadlocked 变量也被用于发送电子邮件的 onError 任务中。由于变量被锁定在循环中以进行写入,并且脚本任务在 onError 完成之前从未真正失败,因此变量保持锁定状态。添加lock for one write代码后,一切正常。

感谢您的帮助、解释和回答。

于 2014-09-05T11:51:18.430 回答
0

正是我正在寻找的,如果对 SPROC 的特定调用在我的捕获中返回 SQL 错误,则退出。

  catch (SqlException ex)
                {
                    ExceptionLogging.SendExcepToDB(ex);
                    Dts.TaskResult = (int)ScriptResults.Failure;
                    return;
                } 
于 2018-02-02T15:32:27.677 回答
0

我没有足够好的“声誉”,所以我必须发布一个答案......锁定变量将阻止事件处理程序在您失败时工作!

因此,在脚本组件失败之前,释放变量是一个很好的做法。

在 catch 语句中解锁所有内容的更直接代码只需执行以下操作:

Dts.Variables.Unlock();

无需建立新的变量对象来解锁它们。

于 2019-12-06T16:49:42.543 回答