2017-10-19 177 views
3

我正在将管道分隔的平面文件加载到临时表中。在加载过程中,SSIS脚本组件在一行上执行一些操作。它可以根据另一个字段中的值在一个字段中设置标志,为某些列添加前缀或应用格式。例如,如果缺少日期,则该字段被分配为默认日期。 (如果Row.EndDate_isNull,则Row.EndDate = defaultDate)如何在SSIS脚本组件中按名称循环访问列?

当需要将相同的转换应用于一系列行时,这些脚本变得很麻烦。例如,医疗记录文件可以用三个字段来描述9个诊断的每一个:Diagnosis01_Date,Diagnosis01_Code,Diagnosis01_System .... Diagnosis09_Date,Diagnosis09_Code,Diagnosis09_System。

我想使用一个循环来执行9个组的3个字段中的每一个的操作,而不是写入相同的操作9次。

如果我正在处理VB中的一个集合,例如,我会写这样的事情在Input0_ProcessInputRow子:

For i = 1 to 9 
    row.("Diagnosis0"+ i + "_Date").Value = diagnosisDate 
    row.("Diagnosis0"+ i + "_System").value = "ICD10" 
next i 

在SSIS对象模型,但是,列暴露Input0Buffer的属性和我找不到一种方法来使用变量来引用它们。那么,如何可以我创建了一个在SSIS脚本组件中按名称对列进行操作的循环?

编辑:我发现以下来源,特别是前两个,在我对这个问题进行研究时会有所帮助。似乎应该有一个使用system.reflection的解决方案,但我只是不太了解.NET。

http://agilebi.com/jwelch/2007/10/21/address-columns-generically-in-a-script-task/

http://agilebi.com/jwelch/2007/06/02/xml-destination-script-component/

http://microsoft-ssis.blogspot.com/2010/12/do-something-for-all-columns-in-your.html

http://toddmcdermid.blogspot.com/2011/05/iterating-over-columns-in-ssis-script.html

http://bidn.com/blogs/MikeDavis/ssis/1800/ssis-for-each-column-in-a-data-flow

https://social.msdn.microsoft.com/Forums/en-US/edbac1df-f05f-40db-820a-e009fae201a4/using-script-destination-object-to-create-and-write-to-new-text-file?forum=sqlintegrationservices&forum=sqlintegrationservices

https://social.msdn.microsoft.com/Forums/en-US/757d11c8-8ad4-4021-a959-1d13c8dfdaa7/how-to-run-a-loop-for-all-columns-in-script-component-input-column-collection-for-each-row?forum=sqlintegrationservices

How can I get the column Value in Script Component in SSIS?

回答

4

简单的解决方法

您可以在List(of string)使用循环存储列名,并使用Row.GetType().GetProperties()动态操作列。

例子:

注意:您要导入System.ReflectionSystem.LinqSystem.Collections.Generic

Dim lstDateColumns as new List(of string) 
Dim lstSystemColumns as new List(of string) 

For i = 1 to 9 
    lstDateColumns.Add("Diagnosis0" & i.toString() & "_Date") 
    lstSystemColumns.Add("Diagnosis0" & i.toString() & "_System") 
Next 


For each dataColumn as PropertyInfo in Row.GetType().GetProperties() 


    If lstDateColumns.Contains(dataColumn.Name) Then 

       dataColumn.SetValue(Row, diagnosisDate, Nothing) 

    ElseIf lstSystemColumns.Contains(dataColumn.Name) Then 

       dataColumn.SetValue(Row, "ICD10", Nothing) 

    End IF 
Next 

而且你可以从列表上的列名称进行筛选

Dim lstDateColumns As New List(Of String) 
    Dim lstSystemColumns As New List(Of String) 

    For i As Integer = 1 To 9 
     lstDateColumns.Add("Diagnosis0" & i.ToString() & "_Date") 
     lstSystemColumns.Add("Diagnosis0" & i.ToString() & "_System") 
    Next 

    For Each dataColumn As PropertyInfo In Row.GetType().GetProperties().Where(Function(x) lstDateColumns.Contains(x.Name)) 

     dataColumn.SetValue(Row, diagnosisDate, Nothing) 

    Next 


    For Each dataColumn As PropertyInfo In Row.GetType().GetProperties().Where(Function(x) lstSystemColumns.Contains(x.Name)) 

     dataColumn.SetValue(Row, "ICD10", Nothing) 

    Next 

参考

+2

我看到,这让我有一部分的方式 - 它将使我遍历我的领域,因为他们是在列表中。有没有办法避免迭代源代码中的所有列? – DataWriter

+0

我是否担心循环遍历所有列的开销不合理? – DataWriter

+1

你说得对。我认为你可以使用linq过滤列名。几点,我会更新 – Hadi