3

私の質問が適切に説明されていない場合は、お詫び申し上げます。私は .Net / C# / SSIS 初心者です。また、すでに回答があった場合はお詫び申し上げます。ここと Google で数時間検索してみましたが、うまくいきませんでした。

背景: SharePoint 365 リストからデータ行を取得し、特定の列をピボット解除して、SQL Server テーブルにインポートできる形式にする必要があります。SSIS には Odata ソースと組み込みの Unpivot コンポーネントがあることを認識しており、それらを概念実証に使用することに成功しました。

ただし、ソース SharePoint リストからアンピボットする列の数は可変であるため、カスタム スクリプト コンポーネントが必要だと思います。ほぼ毎月、新しい列が追加されます (SharePoint の財務予測 "ツール" に関連し、最新の予測月が変わります)。私の理解では、設計時にソース列を SSIS で定義する必要があるため、ソース列が変更されている場合、SSIS データ フローを毎月手動で変更せずにこれに対処する唯一の方法は、Odata ソースとアンピボットをプログラムで結合することです。関数をカスタム スクリプト コンポーネントに組み込みます。

アンピボットのロジックを理解している、または理解できる。私が苦労している部分は、特定のリストに実際に接続して公開する方法です。これは、ループして出力列へのマッピングを実行できるリストとしてのデータ行/列です。

要求されたガイダンスの「出発点」は次のとおりです。1) 標準の SSIS Odata 接続マネージャーを使用して、問題の SharePoint サイトを作成し、正常に接続しました。2) ビジュアル デザイナで、標準の「スクリプト コンポーネント」、タイプ = ソースを作成しました。3) スクリプト コンポーネントのプロパティから、Odata 接続マネージャーを「myConnection」という名前に関連付けます。4) ヘルプが必要 -> スクリプト コンポーネント内で、特定のリストへの接続を開き、その内容を読み取り、アンピボット ロジックを実行します。

説明のために、ソースは SharePoint リストで、Study と Site というタイトルの 2 つの「固定」文字列列と、月末の日付に一致する名前を持つ可変数の列 (例: 2016 年 9 月 30 日、2016 年 10 月 31 日、など) 整数値を含みます。スタディとサイトのソース列を同じ名前の宛先列にマップし、列名が ProjectionMonth にマップされ、整数値が ProjectionValue にマップされている月の列のピボットを解除したいと考えています。

これが私が念頭に置いている基本的なアルゴリズムです(これはコンパイルできないことに気づきました-それが私があなたの助けを必要とするところです!):

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

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    IDTSConnectionManager100 connMgr;
    SqlConnection sqlConn;      // from MSDN tutorial, but I don't know how to adapt to Odata/SharePoint 365 list
    SqlDataReader sqlReader;    // not sure how to adapt

    public override void AcquireConnections(object Transaction)
    {
        connMgr = this.Connections.myConnection;
        sqlConn = (SqlConnection)connMgr.AcquireConnection(null);  // This is from MSDN tutorial, but I don't know how to adapt to Odata

    }

    public override void PreExecute()
    {
        //Not sure how to adapt to odata to read specific SharePoint list
        SqlCommand cmd = new SqlCommand("SELECT * FROM <some sharepoint list>", sqlConn);
        sqlReader = cmd.ExecuteReader();

    }

    public override void PostExecute()
    {
        sqlReader.Close();  // Not sure how to adapt.
    }

    public override void CreateNewOutputRows()
    {

        string myStudy;
        string mySite;
        string myProjectionMonth;
        string myProjectionValue;

        // This is a rough representation of the logic needed.
        // I realize that the actual code to access column values / names depends on the class(es) I need to use, but not sure what those classes are / how to access
        foreach (myListRow in sqlConn.rows)
        {
            myStudy = myListRow.Columns["Study"].value;
            mySite = myListRow.Columns["Site"].value;

            foreach (myColumn in myListRow.Columns)

                if (DateTime.TryParse(myColumn.Name, out dateValue))
                {
                    myProjectionMonth = myColumn.Name;
                    myProjectionValue = myColumn.Value;

                    Output0Buffer.AddRow();
                    Output0Buffer.Study = myStudy;
                    Output0Buffer.Site = mySite;
                    Output0Buffer.ProjectionMonth = myProjectionMonth;
                    Output0Buffer.ProjectionValue = myProjectionValue;

                }
        }
    }

}

編集:例として、ソースの SharePoint リストに次のものが含まれているとします。

Study   Site    9/30/2016   10/31/2016
123     ABC     5           10

スクリプト コンポーネントでリストに接続し、その内容を読み取り、最終的に SQL Server にロードするために次のピボットされていないデータ セットを返します。

Study   Site    ProjectionMonth     ProjectionValue
123     ABC     9/30/2016           5
123     ABC     10/31/2016          10
4

1 に答える 1

2

したがって、これはおそらく理想的な方法ではなく、私が望んでいた標準の SSIS Odata 接続マネージャーを活用していません...しかし、技術的には仕事を成し遂げており、今のところ私にとっては十分です.

もしあれば、提案されたフィードバック/改善/などに興味があります。

#region Namespaces
using System;
using Microsoft.SharePoint.Client;
using System.Security;
using System.Collections.Generic;
#endregion

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    public override void CreateNewOutputRows()
    {
        // Connect to SharePoint
        ClientContext context = new ClientContext("https://<redacted>.sharepoint.com/Development");
        SecureString passWord = new SecureString();

        foreach (char c in Variables.sharepointPassword.ToCharArray()) passWord.AppendChar(c);
        context.Credentials = new SharePointOnlineCredentials("<redacted>@<redacted>.onmicrosoft.com", passWord);

        // Define the target list
        List EnrollmentList = context.Web.Lists.GetByTitle("Enrollment Projections");

        // Find all fields in the target list
        FieldCollection myFields = EnrollmentList.Fields;
        context.Load(myFields);
        context.ExecuteQuery();

        // Load all rows from the target list
        CamlQuery query = CamlQuery.CreateAllItemsQuery(100);
        ListItemCollection items = EnrollmentList.GetItems(query);
        context.Load(items);
        context.ExecuteQuery();

        //Store valid date fields
        List<Field> myDateFields = new List<Field>();

        foreach (Field tempField in myFields)
        {
            DateTime tempDate;

            if (DateTime.TryParse(tempField.Title, out tempDate))
            {
                myDateFields.Add(tempField);
            }
        }

        string myStudy;
        string mySite;
        string myMonth;
        string myValue;

        foreach (ListItem listItem in items)
        {
            myStudy = listItem["Study"].ToString();
            mySite = listItem["Site"].ToString();

            foreach (Field tempField in myDateFields)
            {
                myMonth = tempField.Title;
                myValue = listItem[tempField.InternalName.ToString()].ToString();

                Output0Buffer.AddRow();
                Output0Buffer.Study = myStudy;
                Output0Buffer.Site = mySite;
                Output0Buffer.ProjectedMonth = myMonth;
                Output0Buffer.ProjectedValue = Convert.ToInt32(myValue);
            }
        }
    }
}
于 2016-08-15T04:45:03.843 に答える