0

我正在使用以下代码在 C# 中编写 ssis 包,当我编写此代码时出现错误

    using System;
    using System.Data;
    using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
    using Microsoft.SqlServer.Dts.Runtime.Wrapper;
    using System.Text.RegularExpressions;

    [Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
    public class ScriptMain : UserComponent
    {

        public override void PreExecute()
        {
            base.PreExecute();
        }
        public override void PostExecute()
        {
            base.PostExecute();
        }
        string toreplace = "[~!@#$%^&*()_+`{};':,./<>?]";
        string replacewith = "";
        public override void Input0_ProcessInputRow(Input0Buffer Row)
        {
            Regex reg = new Regex(toreplace);
            Row.NaN = reg.Replace(Row.Na, replacewith);


        }

    }

错误是

The best overloaded method match for 
'System.Text.RegularExpressions.Regex.Replace(string,System.Text.RegularExpressions.MatchEvaluator)' has some invalid arguments

Na是输入列和NaN输出列都是 varchar,在 Inpout 列中有特殊字符。

例外:

System.ArgumentNullException
System.ArgumentOutofRangeException

这是 SSIS 包中 BufferWrapper 中的代码

/* THIS IS AUTO-GENERATED CODE THAT WILL BE OVERWRITTEN! DO NOT EDIT!
*  Microsoft SQL Server Integration Services buffer wrappers
*  This module defines classes for accessing data flow buffers
*  THIS IS AUTO-GENERATED CODE THAT WILL BE OVERWRITTEN! DO NOT EDIT! */



    using System;
    using System.Data;
    using Microsoft.SqlServer.Dts.Pipeline;
    using Microsoft.SqlServer.Dts.Pipeline.Wrapper;

    public class Input0Buffer: ScriptBuffer

    {
        public Input0Buffer(PipelineBuffer Buffer, int[] BufferColumnIndexes, OutputNameMap OutputMap)
            : base(Buffer, BufferColumnIndexes, OutputMap)
        {
        }

        public BlobColumn Na
        {
            get
            {
                return (BlobColumn)Buffer[BufferColumnIndexes[0]];
            }
        }
        public bool Na_IsNull
        {
            get
            {
                return IsNull(0);
            }
        }

        public Int32 NaN
        {
            set
            {
                this[1] = value;
            }
        }
        public bool NaN_IsNull
        {
            set
            {
                if (value)
                {
                    SetNull(1);
                }
                else
                {
                    throw new InvalidOperationException("IsNull property cannot be set to False. Assign a value to the column instead.");
                }
            }
        }

        new public bool NextRow()
        {
            return base.NextRow();
        }

        new public bool EndOfRowset()
        {
            return base.EndOfRowset();
        }

    }

数据流

在此处输入图像描述

脚本组件,输入列

在此处输入图像描述

脚本组件,实际脚本

在此处输入图像描述

4

1 回答 1

4

您的代码大部分都很好。您没有测试该Na列是否为 NULL。也许您的源数据不允许空值,因此无需测试。

您可以通过在成员级别限定 Regex 并在 PreExecute 方法中实例化它来提高性能,但这只是性能问题。与您收到的错误消息无关。

你可以看到我的包裹和预期的结果。我向下发送了 4 行,其中 1 行为 NULL 值,1 行不应更改,2 行需要更改。

我的数据流

我已更新我的数据流以匹配您在变色龙问题中使用的步骤。

数据流

我的来源查询

我生成 2 列数据和 4 行。与您的原始问题匹配的 Na 列是 varchar 类型。列 Agency_Names 被强制转换为已弃用的 Text 数据类型以匹配您的后续更新。

SELECT 
    D.Na
,   CAST(D.Na AS text) AS Agency_Names
FROM
(
SELECT 'Hello world' AS Na
UNION ALL SELECT 'man~ana'
UNION ALL SELECT 'p@$$word!'
UNION ALL SELECT NULL
) D (Na);

数据转换

我在我的 OLE DB 源之后添加了一个数据转换转换。反映您所做的事情,我将 my 转换为长度为 50Agency_Name的数据类型,string [DT_STR]并将其别名为“Agency_Name 的副本”。

数据转换

元数据

此时,我验证我的数据流的元数据是 DT_STR 或 DT_WSTR 类型,这是即将调用的正则表达式的唯一允许输入。我确认这Copy of Agency_Names是预期的数据类型。

在此处输入图像描述

脚本任务

我将 ReadOnly 用法分配给列NaCopy of Agency_Name并将后者命名为“AgencyNames”。

在此处输入图像描述

我添加了 2 个输出列:与您的原始问题匹配的 NaN 并创建了 AgencyNamesCleaned。这些都配置为 DT_STR,代码页 1252,长度为 50。

在此处输入图像描述

这是我使用的脚本。

public class ScriptMain : UserComponent
{

    string toreplace = "[~!@#$%^&*()_+`{};':,./<>?]";
    string replacewith = "";


    public override void Input0_ProcessInputRow(Input0Buffer Row)
    {
        Regex reg = new Regex(toreplace);

        // Test for nulls otherwise Replace will blow up
        if (!Row.Na_IsNull)
        {
            Row.NaN = reg.Replace(Row.Na, replacewith);
        }
        else
        {
            Row.NaN_IsNull = true;
        }

        if (!Row.AgencyNames_IsNull)
        {
            Row.AgencyNamesCleaned = reg.Replace(Row.AgencyNames, replacewith);
        }
        else
        {
            Row.AgencyNamesCleaned_IsNull = true;
        }
    }

}

根本原因分析

我认为您的核心问题可能是Na您拥有的列不是字符串兼容类型。Sriram的评论很到位。如果我查看列的自动生成代码Na,在我的示例中我看到

    public String Na
    {
        get
        {
            return Buffer.GetString(BufferColumnIndexes[0]);
        }
    }
    public bool Na_IsNull
    {
        get
        {
            return IsNull(0);
        }
    }

您的源系统提供了元数据,因此 SSIS 认为该列是二进制数据。也许它是主机中的 NTEXT/TEXT 或 n/varchar(max)。您需要做一些事情以使其成为正则表达式的兼容操作数。我会清理源中的列类型,但如果这不是一个选项,请使用Data Conversion转换将其转换为 DT_STR/DT_WSTR 类型。

结局

您可以在附加到我的第一张图片的数据查看器中观察到,NaN 和 AgencyNamesCleaned 已正确剥离了违规字符。此外,您可以观察到我的脚本任务没有像您的那样附有红色 X。这表明脚本处于无效状态。

由于您从数据转换组件创建了“Agency_Names 的副本”列作为 DT_TEXT,将其连接到脚本组件,然后更改了数据转换组件中的数据类型,因此您的脚本上的红色 X 可能会通过解决转换刷新其元数据。打开脚本并单击重新编译(ctrl-shift-b)以获得良好的效果。

reg.Replace(...您的代码中不应有下划线。如果有,那么您的问题的另一个方面尚未得到沟通。在这一点上,我最好的建议是重新创建一个概念验证包,正如我所描述的那样,如果它有效,它就会成为一个练习,找出你有工作和没有工作之间的区别。

于 2013-08-14T03:03:58.567 回答