1

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

“Add stuff here.Inputs[Derived Column Input].Columns[ad_zip]” on “Add stuff here” 的使用类型为 READONLY,但未被表达式引用。从可用输入列列表中删除该列,或在表达式中引用它。

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

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

3 回答 3

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);
            }
        }
    }
于 2015-01-09T10:52:04.420 回答
0

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

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

dc.Comp.ReinitializeMetaData();

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

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

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

但!您必须在修改完组件的任何其他元数据(附加其他组件、添加新的输入或输出列等)后执行此操作,因为这些都会触发ReinitializeMetaData组件上的方法,该方法会自动设置(或重置VirtualInputColumn)所有 UT_IGNOREDUsageTypeUT_READONLY.

所以一些示例代码:

// define EzSourceComponent with SourceColumnToIgnore output column, SomeConnection for destination

EzDerivedColumn dc = new EzDerivedColumn(this);
dc.AttachTo(EzSourceComponent);
dc.Name = "Errors, Go Away";

dc.InsertOutputColumn("NewDerivedColumn");
dc.Expression["NewDerivedColumn"] = "I was inserted!";            

// Right here, UsageType is UT_READONLY
Console.WriteLine(dc.VirtualInputCol("SourceColumnToIgnore").UsageType.ToString());

EzOleDbDestination d = new EzOleDbDestination(f);
d.Name = "Destination";
d.Connection = SomeConnection;
d.Table = "dbo.DestinationTable";
d.AccessMode = AccessMode.AM_OPENROWSET_FASTLOAD;
d.AttachTo(dc);

// Now we can set usage type on columns to remove them from the available inputs.
// Note the false boolean at the end.
// That's required to not trigger ReinitializeMetadata for usage type changes.
dc.SetUsageType(0, "SourceColumnToIgnore", DTSUsageType.UT_IGNORED, false);

// Now UsageType is UT_IGNORED and if you saved the package and viewed it,
// you'll see this column has been removed from the available input columns
// ... and the warning for it has gone away!
Console.WriteLine(dc.VirtualInputCol("SourceColumnToIgnore").UsageType.ToString());
于 2014-12-01T18:01:15.907 回答
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。

于 2017-03-08T09:44:31.637 回答