Partilhar via


Carregando a saída de um pacote local

se aplica a:SQL Server SSIS Integration Runtime no Azure Data Factory

Os aplicativos cliente podem ler a saída dos pacotes do Integration Services quando a saída é salva em destinos do SQL Server usando ADO.NET ou quando a saída é salva em um destino de arquivo simples usando as classes no namespace System.IO. No entanto, um aplicativo cliente também pode ler a saída de um pacote diretamente da memória, sem a necessidade de uma etapa intermediária para persistir os dados. A chave para essa solução é o namespace Microsoft.SqlServer.Dts.DtsClient, que contém implementações especializadas do IDbConnection, IDbCommande IDbDataParameter interfaces do System.Data namespace. O assembly Microsoft.SqlServer.Dts.DtsClient.dll é instalado por padrão no %ProgramFiles%\Microsoft SQL Server\100\DTS\Binn.

Importante

O procedimento descrito neste artigo, que usa a biblioteca DtsClient, funciona apenas para pacotes implantados com o modelo de implantação de pacote (ou seja, com a opção /SQL, /DTSou /File). Este procedimento não funciona para pacotes implantados com o modelo de implantação de servidor (ou seja, com a opção /ISServer). Para consumir a saída de um pacote local implantado com o modelo de implantação de servidor (ou seja, com a opção /ISServer), use o Data Streaming Destination em vez do procedimento descrito neste artigo.

Observação

O procedimento descrito neste tópico requer que a propriedade DelayValidation da tarefa Fluxo de Dados e de quaisquer objetos pai seja definida como seu valor padrão de False.

Descrição

Este procedimento demonstra como desenvolver um aplicativo cliente em código gerenciado que carrega a saída de um pacote com um destino DataReader diretamente da memória. As etapas resumidas aqui são demonstradas no exemplo de código a seguir.

Para carregar a saída do pacote de dados em um aplicativo cliente

  1. No pacote, configure um destino DataReader para receber a saída que você deseja ler no aplicativo cliente. Dê ao destino DataReader um nome descritivo, pois você usará esse nome posteriormente em seu aplicativo cliente. Anote o nome do destino DataReader.

  2. No projeto de desenvolvimento, defina uma referência ao namespace Microsoft.SqlServer.Dts.DtsClient localizando o assembly Microsoft.SqlServer.Dts.DtsClient.dll. Por padrão, esse assembly é instalado no C:\Arquivos de Programas\Microsoft SQL Server\100\DTS\Binn. Importe o namespace para seu código usando a instrução C# Using ou Visual Basic Imports.

  3. Em seu código, crie um objeto do tipo DtsClient.DtsConnection com uma cadeia de conexão que contenha os parâmetros de linha de comando exigidos por dtexec.exe para executar o pacote. Para obter mais informações, consulte dtexec Utility. Em seguida, abra a conexão com essa cadeia de conexão. Você também pode usar o utilitário dtexecui para criar visualmente a cadeia de conexão necessária.

    Observação

    O código de exemplo demonstra o carregamento do pacote do sistema de arquivos usando a sintaxe /FILE <path and filename>. No entanto, você também pode carregar o pacote do banco de dados MSDB usando a sintaxe /SQL <package name> ou do repositório de pacotes do Integration Services usando a sintaxe /DTS \<folder name>\<package name>.

  4. Crie um objeto do tipo DtsClient.DtsCommand que usa o DtsConnection criado anteriormente e defina sua propriedade CommandText para o nome do destino DataReader no pacote. Em seguida, chame o ExecuteReader método do objeto de comando para carregar os resultados do pacote em um novo DataReader.

  5. Opcionalmente, você pode parametrizar indiretamente a saída do pacote usando a coleção de objetos DtsDataParameter no objeto DtsCommand para passar valores para variáveis definidas no pacote. Dentro do pacote, você pode usar essas variáveis como parâmetros de consulta ou em expressões para afetar os resultados retornados ao destino DataReader. Você deve definir essas variáveis no pacote no namespace DtsClient antes de poder usá-las com o objeto DtsDataParameter de um aplicativo cliente. (Talvez seja necessário clicar no botão da barra de ferramentas Escolher colunas variáveis na janela variáveis para exibir a coluna Namespace .) No código do cliente, quando você adiciona um DtsDataParameter à coleção Parameters doDtsCommand do , omita a referência do namespace DtsClient do nome da variável. Por exemplo:

    command.Parameters.Add(new DtsDataParameter("MyVariable", 1));  
    
  6. Chame o método Read do DataReader repetidamente, conforme necessário, para percorrer as linhas de dados de saída. Use os dados ou salve-os para uso posterior no aplicativo cliente.

    Importante

    O método Read desta implementação do DataReader retorna true mais uma vez após a última linha de dados ter sido lida. Isso dificulta o uso do código usual que percorre o DataReader enquanto Read retorna verdadeiro. Se o código tentar fechar o DataReader ou a conexão depois de ler o número esperado de linhas, sem uma chamada final adicional para o método Read, o código gerará uma exceção sem tratamento. No entanto, se o código tentar ler dados nessa iteração final por meio de um loop, quando de leitura ainda retornar verdadeiro, mas a última linha tiver sido passada, o código gerará um ApplicationException não tratado com a mensagem "O IDataReader do SSIS já passou do final do conjunto de resultados". Esse comportamento é diferente de outras implementações DataReader. Portanto, ao usar um loop para ler as linhas no DataReader enquanto Read retorna true , você precisa escrever código para capturar, testar e descartar esse ApplicationException antecipado na última chamada bem-sucedida para o método Read. Ou, se você souber com antecedência o número de linhas esperado, você pode processar as linhas e, em seguida, chamar o método Read mais uma vez antes de fechar o DataReader e a conexão.

  7. Chame o Dispose método do DtsCommand objeto. Isso é particularmente importante se você tiver usado qualquer DtsDataParameter objetos.

  8. Feche o DataReader e os objetos de conexão.

Exemplo

O exemplo a seguir executa um pacote que calcula um único valor agregado e salva o valor em um destino DataReader e, em seguida, lê esse valor do DataReader e exibe o valor em uma caixa de texto em um Windows Form.

O uso de parâmetros não é necessário ao carregar a saída de um pacote em um aplicativo cliente. Se você não quiser usar um parâmetro, você pode omitir o uso da variável no DtsClient namespace e omitir o código que usa o DtsDataParameter objeto.

Para criar o pacote de teste

  1. Crie um novo pacote do Integration Services. O código de exemplo usa "DtsClientWParamPkg.dtsx" como o nome do pacote.

  2. Adicione uma variável do tipo String no namespace DtsClient. O código de exemplo usa Country como o nome da variável. (Talvez seja necessário clicar no botão da barra de ferramentas Escolher colunas variáveis na janela variáveis para exibir a coluna Namespace .)

  3. Adicione um gerenciador de conexões OLE DB que se conecte ao banco de dados de exemplo AdventureWorks2022.

  4. Adicione uma tarefa de fluxo de dados ao pacote e alterne para a superfície de design Fluxo de Dados.

  5. Adicione uma fonte OLE DB ao fluxo de dados e configure-a para usar o gerenciador de conexões OLE DB criado anteriormente e o seguinte comando SQL:

    SELECT * FROM Sales.vIndividualCustomer WHERE CountryRegionName = ?  
    
  6. Clique em Parâmetros e, na caixa de diálogo Definir parâmetros de consulta, mapeie o único parâmetro de entrada na consulta, Parameter0, para a variável DtsClient::Country.

  7. Adicione uma transformação Agregada ao fluxo de dados e conecte a saída da fonte OLE DB à transformação. Abra o Editor de Transformação Agregada e configure-o para executar uma operação "Contar tudo" em todas as colunas de entrada (*) e para gerar o valor agregado com o alias CustomerCount.

  8. Adicione um destino DataReader ao fluxo de dados e conecte a saída da transformação Aggregate ao destino DataReader. O código de exemplo usa "DataReaderDest" como o nome do DataReader. Selecione a única coluna de entrada disponível, CustomerCount, para o destino.

  9. Salve o pacote. O aplicativo de teste criado em seguida executará o pacote e recuperará sua saída diretamente da memória.

Para criar o aplicativo de teste

  1. Crie um novo aplicativo do Windows Forms.

  2. Adicione uma referência ao namespace Microsoft.SqlServer.Dts.DtsClient navegando até o assembly de mesmo nome em %ProgramFiles%\Microsoft SQL Server\100\DTS\Binn.

  3. Copie e cole o código de exemplo a seguir no módulo de código do formulário.

  4. Modifique o valor da variável dtexecArgs conforme necessário para que ela contenha os parâmetros de linha de comando exigidos por dtexec.exe para executar o pacote. O código de exemplo carrega o pacote do sistema de arquivos.

  5. Modifique o valor da variável dataReaderName conforme necessário para que ela contenha o nome do destino DataReader no pacote.

  6. Coloque um botão e uma caixa de texto no formulário. O código de exemplo usa btnRun como o nome do botão e txtResults como o nome da caixa de texto.

  7. Execute o aplicativo e clique no botão. Após uma breve pausa enquanto o pacote é executado, você verá o valor agregado calculado pelo pacote (a contagem de clientes no Canadá) exibido na caixa de texto do formulário.

Código de exemplo

Imports System.Data  
Imports Microsoft.SqlServer.Dts.DtsClient  
  
Public Class Form1  
  
  Private Sub btnRun_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRun.Click  
  
    Dim dtexecArgs As String  
    Dim dataReaderName As String  
    Dim countryName As String  
  
    Dim dtsConnection As DtsConnection  
    Dim dtsCommand As DtsCommand  
    Dim dtsDataReader As IDataReader  
    Dim dtsParameter As DtsDataParameter  
  
    Windows.Forms.Cursor.Current = Cursors.WaitCursor  
  
    dtexecArgs = "/FILE ""C:\...\DtsClientWParamPkg.dtsx"""  
    dataReaderName = "DataReaderDest"  
    countryName = "Canada"  
  
    dtsConnection = New DtsConnection()  
    With dtsConnection  
      .ConnectionString = dtexecArgs  
      .Open()  
    End With  
  
    dtsCommand = New DtsCommand(dtsConnection)  
    dtsCommand.CommandText = dataReaderName  
  
    dtsParameter = New DtsDataParameter("Country", DbType.String)  
    dtsParameter.Direction = ParameterDirection.Input  
    dtsCommand.Parameters.Add(dtsParameter)  
  
    dtsParameter.Value = countryName  
  
    dtsDataReader = dtsCommand.ExecuteReader(CommandBehavior.Default)  
  
    With dtsDataReader  
      .Read()  
      txtResults.Text = .GetInt32(0).ToString("N0")  
    End With  
  
    'After reaching the end of data rows,  
    ' call the Read method one more time.  
    Try  
      dtsDataReader.Read()  
    Catch ex As Exception  
      MessageBox.Show("Exception on final call to Read method:" & ControlChars.CrLf & _  
      ex.Message & ControlChars.CrLf & _  
      ex.InnerException.Message, "Exception on final call to Read method", _  
      MessageBoxButtons.OK, MessageBoxIcon.Error)  
    End Try  
  
    ' The following method is a best practice, and is  
    '  required when using DtsDataParameter objects.  
    dtsCommand.Dispose()  
  
    Try  
      dtsDataReader.Close()  
    Catch ex As Exception  
      MessageBox.Show("Exception closing DataReader:" & ControlChars.CrLf & _  
      ex.Message & ControlChars.CrLf & _  
      ex.InnerException.Message, "Exception closing DataReader", _  
      MessageBoxButtons.OK, MessageBoxIcon.Error)  
    End Try  
  
    Try  
      dtsConnection.Close()  
    Catch ex As Exception  
      MessageBox.Show("Exception closing connection:" & ControlChars.CrLf & _  
      ex.Message & ControlChars.CrLf & _  
      ex.InnerException.Message, "Exception closing connection", _  
      MessageBoxButtons.OK, MessageBoxIcon.Error)  
    End Try  
  
    Windows.Forms.Cursor.Current = Cursors.Default  
  
  End Sub  
  
End Class  
using System;  
using System.Windows.Forms;  
using System.Data;  
using Microsoft.SqlServer.Dts.DtsClient;  
  
namespace DtsClientWParamCS  
{  
  public partial class Form1 : Form  
  {  
    public Form1()  
    {  
      InitializeComponent();  
      this.btnRun.Click += new System.EventHandler(this.btnRun_Click);  
    }  
  
    private void btnRun_Click(object sender, EventArgs e)  
    {  
      string dtexecArgs;  
      string dataReaderName;  
      string countryName;  
  
      DtsConnection dtsConnection;  
      DtsCommand dtsCommand;  
      IDataReader dtsDataReader;  
      DtsDataParameter dtsParameter;  
  
      Cursor.Current = Cursors.WaitCursor;  
  
      dtexecArgs = @"/FILE ""C:\...\DtsClientWParamPkg.dtsx""";  
      dataReaderName = "DataReaderDest";  
      countryName = "Canada";  
  
      dtsConnection = new DtsConnection();  
      {  
        dtsConnection.ConnectionString = dtexecArgs;  
        dtsConnection.Open();  
      }  
  
      dtsCommand = new DtsCommand(dtsConnection);  
      dtsCommand.CommandText = dataReaderName;  
  
      dtsParameter = new DtsDataParameter("Country", DbType.String);  
      dtsParameter.Direction = ParameterDirection.Input;  
      dtsCommand.Parameters.Add(dtsParameter);  
  
      dtsParameter.Value = countryName;  
  
      dtsDataReader = dtsCommand.ExecuteReader(CommandBehavior.Default);  
  
      {  
        dtsDataReader.Read();  
        txtResults.Text = dtsDataReader.GetInt32(0).ToString("N0");  
      }  
  
      //After reaching the end of data rows,  
      // call the Read method one more time.  
      try  
      {  
        dtsDataReader.Read();  
      }  
      catch (Exception ex)  
      {  
        MessageBox.Show(  
          "Exception on final call to Read method:\n" + ex.Message + "\n" + ex.InnerException.Message,  
          "Exception on final call to Read method", MessageBoxButtons.OK, MessageBoxIcon.Error);  
      }  
  
      // The following method is a best practice, and is  
      //  required when using DtsDataParameter objects.  
      dtsCommand.Dispose();  
  
      try  
      {  
        dtsDataReader.Close();  
      }  
      catch (Exception ex)  
      {  
        MessageBox.Show(  
          "Exception closing DataReader:\n" + ex.Message + "\n" + ex.InnerException.Message,  
          "Exception closing DataReader", MessageBoxButtons.OK, MessageBoxIcon.Error);  
      }  
  
      try  
      {  
        dtsConnection.Close();  
      }  
      catch (Exception ex)  
      {  
        MessageBox.Show(  
          "Exception closing connection:\n" + ex.Message + "\n" + ex.InnerException.Message,  
          "Exception closing connection", MessageBoxButtons.OK, MessageBoxIcon.Error);  
      }  
  
      Cursor.Current = Cursors.Default;  
  
    }  
  }  
}  

Ver também

Compreender as diferenças entre a execução local e remota
Carregando e executando um pacote local programaticamente
Carregando e executando um pacote remoto programaticamente