2016-08-14 2136 views
2

如果我的问题未得到充分描述,则表示歉意。我是一个.Net/C#/ SSIS新手。也道歉,如果已经回答,我已经尝试在这里搜索和谷歌几个小时没有运气。SSIS脚本组件源 - 通过Odata从SharePoint 365列表中读取

背景:我需要从SharePoint 365列表中提取数据行,并将某些列未转换为准备导入SQL Server表格的格式。我意识到SSIS有Odata Source和内置的Unpivot组件,并且我已经成功地将这些用于概念验证。

但是,我相信我需要一个自定义脚本组件,因为从源SharePoint列表中取消转换的列数是可变的。每个月左右,都会添加一个新列(它与SharePoint中的财务预测“工具”相关,以及最新的预测月份更改)。我的理解是,在设计时必须在SSIS中定义源列,因此如果我的源列发生更改,我可以考虑解决这个问题的唯一方法就是不用每个月手动更改SSIS数据流,都会以编程方式将Odata源和未转换函数到一个自定义脚本组件。

我明白,或可以弄清楚unpivot逻辑。我正在努力的部分是如何实际连接并公开给定列表,并将数据行/列作为列表进行循环显示,然后执行映射到输出列。

我的请求指导的“出发点”是这样的: 1)使用标准的SSIS Odata连接管理器创建并成功连接到有问题的SharePoint站点。 2)在视觉设计器上创建标准“脚本组件”,类型=源。 3)从脚本组件属性中,将Odata连接管理器与名称“myConnection”关联。 4)需要帮助 - >在脚本组件中,打开到特定列表的连接,读取它的内容,并执行unpivot逻辑。

出于说明的目的,假定源是一个SharePoint列表标题为研究和站点两个“固定”的字符串列,和列具有匹配月末日期名称(可变数目例如2016年9月30日, 10/31/2016等)包含整数值。我想将研究和网站源列映射到相同名称的目标列,并且未映射列名称映射到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设置服务器:

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

回答

1

所以这可能不是这样做的一种理想的方式,并且它没有利用我想要的标准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); 
      } 
     } 
    } 
} 
+0

您好,我昨天用,这不是可能重新使用连接管理器来填充网站/凭据脚本内clientContext结论结束了发现了类似的旅程。我通过传入参数并从中构建SharePointOnlineCredentials对象,最终做了或多或少的工作。 – sasfrog