2016-08-14 6 views
2

Je m'excuse si ma question n'est pas correctement décrite. Je suis un débutant .Net/C#/SSIS. Aussi excusez-vous si vous avez déjà répondu, j'ai essayé de chercher ici et Google pendant quelques heures sans succès. Contexte: J'ai besoin de tirer des lignes de données à partir d'une liste SharePoint 365 et de redimensionner certaines colonnes dans un format prêt à être importé dans une table SQL Server. Je me rends compte que SSIS a une source Odata et un composant Unpivot intégré, et je les ai utilisés avec succès pour la preuve de concept.Source du composant de script SSIS - Lire à partir de la liste SharePoint 365 via Odata

Cependant, je crois que j'ai besoin d'un composant de script personnalisé parce que le nombre de colonnes à déplier de la liste SharePoint source est variable. Chaque mois, une nouvelle colonne sera ajoutée (elle se rapporte à un «outil» de prévision financière dans SharePoint et aux derniers changements de mois prévus). Ma compréhension est que les colonnes source doivent être définies dans SSIS au moment du design, donc si mes colonnes source sont en train de changer, la seule façon de résoudre cela sans modifier manuellement le flux de données SSIS chaque mois est de combiner par programme la source Odata et unpivot fonctions dans un composant de script personnalisé.

Je comprends, ou peux comprendre, la logique non pivot. La partie avec laquelle je me bats est de savoir comment se connecter et exposer une liste donnée et ses lignes/colonnes de données sous la forme de listes que je peux parcourir et effectuer ma mise en correspondance avec les colonnes de sortie.

Mon «point de départ» pour les conseils demandés est la suivante: 1) Créé et connecté avec succès au site SharePoint en question à l'aide du gestionnaire de connexion SSAS standard SSIS. 2) Créer un "Script Component" standard, type = source, sur le concepteur visuel. 3) A partir des propriétés du composant de script, associer le gestionnaire de connexions Odata au nom de "myConnection". 4) Besoin d'aide -> dans le composant de script, ouvrez une connexion à une liste spécifique, lisez son contenu et exécutez une logique non pivot. Supposons que la source soit une liste SharePoint avec deux colonnes de chaînes "fixes" intitulées Etude et Site, et un nombre variable de colonnes dont les noms correspondent aux dates de fin de mois (par exemple, 30/09/2016, 31/10/2016, etc.) contenant des valeurs entières. Je souhaite mapper les colonnes étude et source du site aux colonnes de destination du même nom et redimensionner les colonnes de mois où le nom de colonne est mappé à ProjectionMonth et la valeur entière est mappée à ProjectionValue.

est ici l'algorithme de base que j'ai à l'esprit (je sais que ce n'est pas compilable - c'est là où je besoin de votre aide!):

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; 

       } 
     } 
    } 

} 

Edit: à titre d'exemple, supposons que la source liste SharePoint a les éléments suivants:

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

Je veux le composant de script pour se connecter à la liste, lire son contenu, et renvoyer les données suivantes pivotée définies pour la charge éventuelle dans SQL Serveur:

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

Répondre

1

C'est donc probablement pas un moyen idéal de le faire, et il ne pas tirer parti de la norme SSIS OData Connection Manager que je voulais ... mais il ne se fait techniquement le travail et il est bon assez pour moi, pour le moment.

Serait intéressé par toute suggestion de suggestions/améliorations/etc., si vous en avez.

#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

Salut, j'ai eu un voyage similaire de découverte hier qui a abouti à la conclusion qu'il est impossible de réutiliser un gestionnaire de connexion pour remplir le site/informations d'identification pour un ClientContext dans un script. J'ai fini par faire plus ou moins ce que vous avez fait, en passant des paramètres et en construisant l'objet SharePointOnlineCredentials à partir d'eux. – sasfrog