SQL Server ed ALM su database


Il blog di Alessandro Alpi
Archivio Posts
Anno 2018

Anno 2017

Anno 2016

Anno 2015

Anno 2014

Anno 2013

Anno 2012

Anno 2011

Anno 2010

Anno 2009

Anno 2008

Anno 2007

Anno 2006

Il bypass del Web Service Task con uno script task

Con SQL Server Integration Services è possibile utilizzare un particolare task, chiamato Web service Task, utilizzato proprio per invocare Web services. E' il seguente:


Prendiamo un semplicissimo scenario, il web service di default che Visual Studio 2005 ci propone quando creiamo un progetto Web Service. Il classico Hello World.
L'utilizzo del task è molto semplice. Gli step da seguire per poter usufruire delle sue funzionalità sono i seguenti:

- Creare un connection Manager di tipo HTTP


Nell'esempio ho impostato semplicemente il link http al mio WSDL di prova, ma come potete notare ci sono altre impostazioni molto importanti da poter utilizzare.
Ad esempio è possibile fornire username, password e dominio di accesso, impostare un certificato, definire il timeout, la dimensione del blocco per la scrittura dei dati e testare la connessione.
In alto vi è anche la clip dedicata alle impostazioni di un eventuale proxy.
Siccome questa connessione HTTP è stata appositamente creata per un web service task e siccome avrò bisogno di conoscere la struttura del servizio, e quindi un WSDL, l'url di riferimento comprende il parametro ?WSDL. Chiamiamolo Servizio

- Creare una variabile che conterrà la risposta (o un connection manager File per scrivere la risposta su filesystem)

E' possibile ad esempio creare una variabile di tipo stringa che conterrà la risposta del nostro servizio.



- Creare nella cartella del nostro progetto o su di una posizione nel disco ben definita un file vuoto con estensione .wsdl



- Impostare il Web Service Task come segue:

Fare doppio click sul Web service Task.
Come prima cosa selezionare la http connection che abbiamo creato pocanzi e poi definire nella proprietà WSDLFile il percorso ove il file .wsdl è stato creato.
La terza proprietà, OverwriteWSDLFile, indica se si vuole sovrascrivere il file alla pressione del tasto sottostante, il Download WSDL.
La prima volta, ed ogni volta che la struttura del servizio cambia (e quindi ogni volta che si vuole scaricare il nuovo WSDL) lasciare questa proprietà impostata a True.
A questo punto, premere il tasto Download WSDL e attendere il messaggio di conferma:



Se la proprietà OverwriteWSDLFile è a False, viene restituito un messaggio di errore.
Facoltativamente, potete andare a controllare sul disco e noterete che il file scaricato è effettivamente il WSDL del servizio che dobbiamo invocare.

- Definire la sezione Input

Spostarsi sulla sezione input. Scegliere il servizio (proprietà Service) ed il metodo da eseguire (proprietà Method). Nel caso in cui il metodo abbia parametri, comparirà un'apposita sezione al di sotto della selezione della chiamata. Qui di seguito un esempio di chiamata con un parametro stringa (metodo Message), mentre quello al precedente punto non ne ha alcuno:



Attenzione, perchè per i tipi che non sono considerati primitivi, come possono esserlo interi e stringhe, SSIS non è in grado di fornire il passaggio di parametri. Ad esempio, un metodo definito come il seguente, non restituirà a SSIS nessuna richiesta di parametri input:

<WebMethod()> _
    Public Function NumeroRighe(ByVal ds As DataSet) As Integer
       
Return ds.Tables(0).Rows.Count
    End Function


- Definire la sezione Output

Dopo aver configurato l'input, definiamo l'output selezionando il tipo di container della risposta, File o Variabile. Qui di seguito l'esempio su variabile, dichiarata all'inizio del post:


Eseguendo un ipotetico SSIS che lancia il web service suddetto e che in seguito visualizza il valore della risposta avremo questo comportamento:


Dopo aver introdotto il task, vorrei soffermarmi su alcuni ostacoli che potremmo incontrare nell'usarlo. E vorrei anche giustificare il titolo del post .
Oltre a non poter passare parametri di un certo tipo (da MSDN: "The Web Service task supports parameters of the following data types only: primitive types such as integers and strings; arrays and sequences of primitive types; and enumerations."), vi è da ricordare che tutte le risposte del web service task sono stringhe. Ognuna di esse è la serializzazione del valore/oggetto di ritorno. Quindi ogni stringa contiene l'XML della risposta serializzata. Questo perchè il task non si pone di creare una classe proxy come ad esempio Visual Studio fa quando aggiungiamo una Web Reference.
Abbiamo la possibilità di salvare la stringa su un file xml, è vero, ma se volessimo utilizzare la risposta tipizzandola e castandola in un nostro oggetto all'interno di un package, dovremmo per forza ricorrere alla deserializzazione. E quindi scrivere codice.
Di conseguenza, molto spesso non utilizzo il web service task ma direttamente lo script task, in un modo un po' particolare.

Tramite il tool WSDL.exe usato anche da Visual studio per scrivere la classe proxy dal wsdl, genero la classe proxy.


Aggiungo uno script task e includo al suo interno la classe generata con wsdl.exe (con SSIS 2005 solo VB). Inoltre aggiungo il riferimento a System.Web.Services e System.Xml.



Nello ScriptMain possiamo istanziare il manager del servizio (la nostra classe proxy) per eseguire i metodi da codice. Ricordiamo il metodo d'esempio:

<WebMethod()> _
    Public Function NumeroRighe(ByVal ds As DataSet) As Integer
       
Return ds.Tables(0).Rows.Count
    End Function

Ecco come nello Script eseguo la chiamata:

Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime

Public Class ScriptMain

    Public Sub Main()

        ' istanzio il web service
        Dim objWS As New Service1()


       
' creo una tabella con una riga
        Dim objdt As New DataTable()

        objdt.Columns.Add("col1", GetType(System.String))
        Dim objdr As DataRow = objdt.NewRow()

        objdr("col1") = "PROVA"
        objdt.Rows.Add(objdr)

        ' popolo il dataset
        Dim objDs As New DataSet
        objDs.Tables.Add(objdt)

        ' chiamo il metodo che mi torna il numero di righe della tabella del dataset
        Dim i As Integer = objWS.NumeroRighe(objDs)

        ' ...

        Dts.TaskResult = Dts.Results.Success

    End Sub

End Class

Con questo metodo possiamo muoverci con maggiore libertà sui tipi del framework ed anche su quelli definiti da noi. Esiste comunque un rovescio della medaglia, ed è quello relativo alla manutenzione del codice. Cambiando la struttura del web service, è necessario replicare la nuova classe proxy anche negli script che la utilizzano.
ATTENZIONE
Vi è una soluzione più corretta, ovvero creare una dll strongly signed e metterla in GAC, in modo tale da poter aggiungere il riferimento così come per le altre classi .NET. Quest'ultima è sicuramente la soluzione più pulita, se non vogliamo utilizzare il task di SSIS. Ad ogni modo, il riferimento deve essere aggiunto a livello di Script poichè non è possiible referenziare una DLL a livello globale.
Comunque lascio la firma e la creazione dell'assembly in GAC a Voi.. ecco un link utile per capire meglio come firmare la dll
http://msdn2.microsoft.com/en-us/library/ms247123.aspx

Stay tuned!
Categoria: SSIS 2005 tips
sabato, 15 dic 2007 Ore. 21.09
Statistiche
  • Views Home Page: 585.797
  • Views Posts: 1.043.124
  • Views Gallerie: 610.301
  • n° Posts: 484
  • n° Commenti: 273



















Copyright © 2002-2007 - Blogs 2.0
dotNetHell.it | Home Page Blogs
ASP.NET 2.0 Windows 2003