2017-10-19 179 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