带有EZAPI EzDerivedColumn和输入列的警告消息

时间:2014-06-04 07:44:07

标签: ssis ezapi

使用ezAPI将派生列添加到数据流时,我收到以下警告

  

“在此处添加内容。输入[派生列输入] .Columns [ad_zip]”on“添加   这里的东西“使用类型为READONLY,但未被引用   表达。从可用输入列表中删除列   列,或在表达式中引用它。

我试图删除输入列,但是方法不起作用或者我做错了:

foreach (Microsoft.SqlServer.Dts.Pipeline.Wrapper.IDTSInputColumn100 col in derFull.Meta.InputCollection[0].InputColumnCollection)
{
    Console.WriteLine(col.Name);
    derFull.DeleteInputColumn(col.Name);
}

3 个答案:

答案 0 :(得分:1)

我有以下代码来解决问题。

我是从一个名叫Daniel Otykier的家伙那里得到的。所以他可能是应该归功于它的人......除非他从其他人那里得到它: - )

static public void RemoveUnusedInputColumns(this EzDerivedColumn component)

    {
        var usedLineageIds = new HashSet<int>();

        // Parse all expressions used in new output columns, to determine which input lineage ID's are being used:
        foreach (IDTSOutputColumn100 column in component.GetOutputColumns())
        {
            AddLineageIdsFromExpression(column.CustomPropertyCollection, usedLineageIds);
        }

        // Parse all expressions in replaced input columns, to determine which input lineage ID's are being used:
        foreach (IDTSInputColumn100 column in component.GetInputColumns())
        {
            AddLineageIdsFromExpression(column.CustomPropertyCollection, usedLineageIds);
        }

        var inputColumns = component.GetInputColumns();

        // Remove all input columns not used in any expressions:
        for (var i = inputColumns.Count - 1; i >= 0; i--)
        {
            if (!usedLineageIds.Contains(inputColumns[i].LineageID))
            {
                inputColumns.RemoveObjectByIndex(i);
            }
        }
    }


    static private void AddLineageIdsFromExpression(IDTSCustomPropertyCollection100 columnProperties, ICollection<int> lineageIds)
    {
        int lineageId = 1;

        var expressionProperty = columnProperties.Cast<IDTSCustomProperty100>().FirstOrDefault(p => p.Name == "Expression");
        if (expressionProperty != null)
        {
            // Input columns used in expressions are always referenced as "#xxx" where xxx is the integer lineage ID.
            var expression = expressionProperty.Value.ToString();
            var expressionTokens = expression.Split(new[] { ' ', ',', '(', ')' });

            foreach (var c in expressionTokens.Where(t => t.Length > 1 && t.StartsWith("#") && int.TryParse(t.Substring(1), out lineageId)))
            {
                if (!lineageIds.Contains(lineageId)) lineageIds.Add(lineageId);
            }
        }
    }

答案 1 :(得分:0)

简单但不是100%保证的方法

在EzApi扩展的基础组件上调用ReinitializeMetaData:

dc.Comp.ReinitializeMetaData();

这并不总是尊重EzAPI所拥有的一些自定义和逻辑检查,因此请仔细测试。但是,对于大多数香草组件,这应该可以正常工作。

100%保证方法但需要一种识别要忽略的列的策略

您可以使用EzApi的SetUsageType包装器方法将这些VirtualInputColumns的UsageType属性设置为枚举值DTSUsageType.UT_IGNORED。

但是!您必须在之后完成修改组件的任何其他元数据(附加其他组件,添加新的输入或输出列等),因为每个元素都会触发{组件上的{1}}方法,自动将所有UT_IGNORED ReinitializeMetaData VirtualInputColumn设置(或重置)为UsageType

所以一些示例代码:

UT_READONLY

答案 2 :(得分:0)

我确实遇到了你的问题并找到了解决问题的方法。问题是EzDerivedColumn没有在其类中定义PassThrough。

您只需要将其添加到课程中:

    private PassThroughIndexer m_passThrough;
    public PassThroughIndexer PassThrough
    {
        get
        {
            if (m_passThrough == null)
                m_passThrough = new PassThroughIndexer(this);
            return m_passThrough;
        }
    }

并将ReinitializeMetadataNoCast()改为:

 public override void ReinitializeMetaDataNoCast()
    {
        try
        {
            if (Meta.InputCollection[0].InputColumnCollection.Count == 0)
            {
                base.ReinitializeMetaDataNoCast();
                LinkAllInputsToOutputs();
                return;
            }

            Dictionary<string, bool> cols = new Dictionary<string, bool>();
            foreach (IDTSInputColumn100 c in Meta.InputCollection[0].InputColumnCollection)
                cols.Add(c.Name, PassThrough[c.Name]);
            base.ReinitializeMetaDataNoCast();
            foreach (IDTSInputColumn100 c in Meta.InputCollection[0].InputColumnCollection)
            {
                if (cols.ContainsKey(c.Name))
                    SetUsageType(0, c.Name, cols[c.Name] ? DTSUsageType.UT_READONLY : DTSUsageType.UT_IGNORED, false);
                else
                    SetUsageType(0, c.Name, DTSUsageType.UT_IGNORED, false);
            }
        }
        catch { }
    }

这是其他组件使用的策略。如果您想查看所有代码,可以查看我的EzApi2016@GitHub。我将原始代码从Microsoft更新到SQL Server 2016。