Inicio > .NET > Creando paquetes de SSIS con .NET – Creando data flow Task y elementos internos

Creando paquetes de SSIS con .NET – Creando data flow Task y elementos internos


Se pueden crear paquetes de SQL Server Integration Services (SSIS) programáticamente con .NET, haciendo uso de las librerías que incluye SQL Server 2008. En este post se explica cómo crear data flow task y sus elementos internos.

Serie Creando paquetes de SSIS con .NET

Una vez que agregamos los elementos básicos como creación del paquete y los objetos de conexión, podemos seguir agregando nuevos elementos al paquete que estamos creando usando C# y .NET (puedes guiarte con el primer post de esta serie - Agregando elementos básicos)

Tomaremos como referencia los elementos creados en el primer post de esta serie, para seguir agregándole objetos al paquete que se quiere crear. Para este post crearemos un data flow y algunos elementos internos, tomando como ejemplo un escenario en donde tomaremos data de un archivo de texto y la pasaremos a una tabla en SQL Server.

Creando Dataflow Task

El dataflow task es el objeto que contendrá todo los flujos de trabajo para trabajar con los datos. Para crear el objeto Dataflow Task utilizaremos el siguiente código:

Executable DataFlowExe = pkg.Executables.Add("STOCK:PipelineTask");
TaskHost thMainPipe = DataFlowExe as TaskHost;
thMainPipe.Name = "Carga de tabla";
MainPipe dfTask = thMainPipe.InnerObject as MainPipe;
PrecedenceConstraint constraint = pkg.PrecedenceConstraints.Add(SQLTaskExe, DataFlowExe);

Ya teniendo creado el dataflow task, podemos agregar los objetos internos que conforman el flujo de trabajo a construir.

Creando Flat File Source

Este objeto es que nos permite conectarnos con el origen de los datos para extraer los registros, este origen de datos debe ser un objeto de conexión de tipo Flat File en el cual se define el comportamiento de la información dentro del archivo.

Para crear este tipo de objetos usamos el siguiente código:

IDTSComponentMetaData100 ffSource = dfTask.ComponentMetaDataCollection.New();
ffSource.ComponentClassID = "DTSAdapter.FlatFileSource.2";
ffSource.Name = "FlatFileSource";
ffSource.Description = "Flat file source";
CManagedComponentWrapper ffSrcComponent = ffSource.Instantiate();
ffSrcComponent.ProvideComponentProperties();
ffSrcComponent.SetComponentProperty("RetainNulls", true);

//Asociamos al objeto de conexión
if (ffSource.RuntimeConnectionCollection.Count > 0)
{
ffSource.RuntimeConnectionCollection[0].ConnectionManager = DtsConvert.GetExtendedInterface(pkg.Connections["TXT.Archivo"]);
ffSource.RuntimeConnectionCollection[0].ConnectionManagerID = pkg.Connections["TXT.Archivo"].ID;
}
ffSrcComponent.AcquireConnections(null);
ffSrcComponent.ReinitializeMetaData();
ffSrcComponent.ReleaseConnections();

//Opcional, podemos definir el comportamiento de los campos al momento de ocurrir un error o un truncamiento de los datos
for (int i = 0; i < ffSource.OutputCollection[0].OutputColumnCollection.Count; i++)
{
ffSource.OutputCollection[0].OutputColumnCollection[i].ErrorRowDisposition = DTSRowDisposition.RD_RedirectRow;
ffSource.OutputCollection[0].OutputColumnCollection[i].TruncationRowDisposition = DTSRowDisposition.RD_RedirectRow;
}

Creando SQL Destination

El siguiente paso es crear el destino de los datos, para este caso es una tabla de SQL Server. Para crear este objeto y definir su comportamiento usamos el siguiente código:

IDTSComponentMetaData100 SQLDestination = dfTask.ComponentMetaDataCollection.New();
SQLDestination.ComponentClassID = "DTSAdapter.OLEDBDestination.2";
SQLDestination.Name = "OLEDBDestination";
SQLDestination.Description = "SQL destination";
CManagedComponentWrapper SQLDestComponent = SQLDestination.Instantiate();
SQLDestComponent.ProvideComponentProperties();

//Asociamos con el objeto de conexión de SQL Server
if (SQLDestination.RuntimeConnectionCollection.Count > 0)
{
SQLDestination.RuntimeConnectionCollection[0].ConnectionManager = DtsConvert.GetExtendedInterface(pkg.Connections["OLEDB"]);
SQLDestination.RuntimeConnectionCollection[0].ConnectionManagerID = pkg.Connections["OLEDB"].ID;
}

//Configuramos algunas propiedades del objeto
SQLDestComponent.SetComponentProperty("AccessMode", 3); //Equivale a: Table or view - fast load
SQLDestComponent.SetComponentProperty("OpenRowset", "NombreTabla");
SQLDestComponent.SetComponentProperty("FastLoadOptions", "TABLOCK");
SQLDestComponent.AcquireConnections(null);

//Reinicializamos la metadata del objeto
SQLDestComponent.ReinitializeMetaData();

Conexión de ambos objetos

Finalmente debemos unir ambos objetos, o mejor dicho, trazar por código la conexión de los objetos mapeando la salida de uno con la entrada del otro.

Para realizar esta actividad aplicamos el siguiente código:

//Agregamos el conector
IDTSPath100 path = dfTask.PathCollection.New();
path.AttachPathAndPropagateNotifications(ffSource.OutputCollection[0], SQLDestination.InputCollection[0]);
// Obtenemos el input por defecto del objeto.
IDTSInput100 input = SQLDestination.InputCollection[0];
IDTSVirtualInput100 vInput = input.GetVirtualInput();

foreach (IDTSVirtualInputColumn100 vColumn in vInput.VirtualInputColumnCollection)
{
// Llamamos al método SetUsageType del objeto destino para agregar cada virtual input column como un input column.
SQLDestComponent.SetUsageType(input.ID, vInput, vColumn.LineageID, DTSUsageType.UT_READWRITE);
}
foreach (IDTSInputColumn100 inColumn in SQLDestination.InputCollection[0].InputColumnCollection)
{
// creamos el mapeo
IDTSExternalMetadataColumn100 exColumn = SQLDestination.InputCollection[0].ExternalMetadataColumnCollection[inColumn.Name];
exColumn.Name = inColumn.Name;
SQLDestComponent.MapInputColumn(SQLDestination.InputCollection[0].ID, inColumn.ID, exColumn.ID);
}
SQLDestComponent.ReleaseConnections();

De esta forma completamos el flujo de trabajo que procesaría los registros contenidos en un archivo de texto para enviarlos a una tabla de SQL Server. En la siguiente entrega estaré mostrando un poco cómo crear SQL Task y File System Task.

Nos leemos,

Acerca de estos anuncios
Categorías:.NET Etiquetas: , , , ,
  1. Berenice
    30/01/2012 en 2:45 pm

    interesant y si quiero agregar un condicion split o un merge join

    • 31/01/2012 en 2:13 am

      Hola, actualmente indago en eso… creo que anexaré un post más a esta serie y te comparto el link por aca… dame un par de días :-)

      Gracias por la pregunta.
      Saludos,

  2. Bere
    25/02/2012 en 1:25 pm

    hola Eduardo como estas..tengo el siguiente problema no se si puedas ayudarme
    tengo un script component donde obtengo la ruta del archivo y el nombre (DT_WTSR) y lo quiero transformar a varbinary, como se ve en el siguient codigo:

    FileInfo fileInfo = new FileInfo(Row.rutaarchivo);
    FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read);
    BinaryReader rdr = new BinaryReader(fs);
    byte[] fileData = rdr.ReadBytes((int)fs.Length);

    Row.Imagen = fileData;
    rdr.Close();
    fs.Close();
    el problema es que no me muestra nada en la columna Imagen…
    comopuedo depurar el problema

    • 27/02/2012 en 11:19 am

      Hola, la idea de este script es meter una imagen que está en archivo a un campo de tipo imagen? qué tipo de dato tiene el elemento Row?

      Saludos,

  3. Bere
    27/02/2012 en 9:21 pm

    hola eduardo…asi es row.rutaarchivo unicode string[DT_WSTR] y lo quiero trasformar a varbinary
    pero ahora me marca este error en el script:

    the value is too large to fit in the column data area of the buffer

    saludos

  4. 28/02/2012 en 11:01 am

    Hola Bere, Te recomiendo que la ruta del archivo la guardes en una variable y para el caso de transformar la imagen, puedes apoyarte en el script component, donde leerás la variable en el código .NET y para convertirla en binario para almacenarla en base de datos, puedes guiarte con este vínculo:

    http://www.codeproject.com/Articles/10861/Storing-and-Retrieving-Images-from-SQL-Server-usin

    Cualquier cosa, comenta de nuevo.

    Saludos,

  5. Bere
    12/03/2012 en 1:04 pm

    Hola Eduardo…pues resulta que ya quedo no se si era por problemas de permisos al accesar a la carpeta que contenia la imagen pero quedo resuelto con el codigo que t puse y haciendo pruebas :)

    p.d. aun tengo problemas en el mapeo de los campos ya que ingreso en 3 tablas pero gracias por la ayuda

    • 12/03/2012 en 2:59 pm

      Que bueno que pudiste resolver. Qué problemas de mapeo tienes?

      Saludos,

  6. Berenice
    28/09/2012 en 4:23 pm

    Hola eduardo como estas otra vez molestando para preguntarte sobre el error The column status returned was: “The value violated the schema’s constraint for the column.”.,
    Me aparece cuando paso datos de una tabla fuente a una tabla destino, las cuales son identicas…
    he leido que es por que no se permiten valores nulos y solo hay k habilitar esa opcion en la columna pero que pasa si se trata de una columna primaria… no se si puedas orientarme
    Saludos

    • 28/09/2012 en 7:34 pm

      Hola, gracias por escribir. En esos casos puedes tener dentro del dataflow task el objeto de origen de los datos, luego un derivied column o un script component que te permitar aplicar algun workaround en el caso de los campos unos y de ultimo es que remapeas al destino.

      Cualquier duda, escribe de nuevo.

      Nos leemos

  7. Berenice
    27/05/2013 en 1:58 pm

    Hola Eduardo como te va, te escribo por que tengo una duda…. estoy manejando transacciones en un paquete que lanza a varios paquetes con la propiedad “Required” en TransactionOption, la cuestión es que en un ambiente de pruebas me funciona bien (configurando el servicio de DTC en ambos servidores), pero probandolo en los servidores correctos me marca el siguiente error:
    “The transaction has already been implicitly or explicitly committed or aborted”

    no se si el error persista por algun error de configuracion en alguno de los servidores en cuanto a la configuracion de DTC, inlcuso ya deshabilite mejor el firewall, pero sigue sin funcionar no se si puedas sugerirme que mas puedo revisar o realizar en el manejador de sql por ejemplo.

    Bueno sin mas por el momento espero tu repuesta gracias.
    Saludos

    • 29/05/2013 en 2:51 pm

      Hola Berenice, gracias por escribir. Las veces que he presentado este problema ha sido porque el firewall no tiene la regla correspondiente para permitir la entrada y salida de información para MSDTC.exe. Has probado agregando la excepción al Firewall de Windows (o si usas alguno corporativo) y el puerto 135? http://support.microsoft.com/kb/306843

      Saludos,

  8. Berenice
    30/05/2013 en 2:05 pm

    Gracias por contestar Eduardo…pero ya he configurado el firewall con dichas reglas y el puerto 135, también he deshabilitado el firewall por si las dudas.. pero aun sigue sin funcionar, voy a probar con la herramienta que tiene el link que me diste sobre el ping del DTC.

    saludos gracias

  1. 03/01/2012 en 5:21 pm
  2. 24/01/2012 en 1:16 pm
  3. 26/01/2012 en 3:45 pm
  4. 26/01/2012 en 6:26 pm

Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 1.449 seguidores

A %d blogueros les gusta esto: