Agregar tareas mediante programación
Se pueden agregar tareas a los siguientes tipos de objetos en el motor en tiempo de ejecución:
Estas clases se consideran contenedores y todas ellas heredan la propiedad Executables. Los contenedores pueden contener una colección de tareas, que son objetos ejecutables procesados por el motor en tiempo de ejecución durante la ejecución del contenedor. El orden de ejecución de los objetos en la colección se determina mediante cualquier conjunto PrecedenceConstraint de cada tarea en los contenedores. Las restricciones de precedencia habilitan la bifurcación de la ejecución en función del éxito, error o finalización de Executable en la colección.
Cada contenedor incluye una colección Executables que contiene los objetos Executable individuales. Cada tarea ejecutable hereda e implementa el método Executable.Execute y el método Executable.Validate. El motor en tiempo de ejecución llama a estos dos métodos para procesar cada Executable.
Para agregar una tarea a un paquete, necesita un contenedor con una colección Executables existente. En la mayoría de las ocasiones, la tarea que agregará a la colección es un paquete. Para agregar el nuevo ejecutable de tarea a la colección de dicho contenedor, debe llamar al método Executables.Add. El método tiene un parámetro único, una cadena, que contiene los valores CLSID, PROGID, moniker STOCK o TaskInfo.CreationName de la tarea que agrega.
Nombres de tarea
Aunque puede especificar una tarea por nombre o por identificador, el moniker STOCK es el parámetro utilizado con mayor frecuencia en el método Executables.Add. Para agregar a un ejecutable una tarea identificada por el moniker STOCK, utilice la sintaxis siguiente:
Executable exec = package.Executables.Add("STOCK:BulkInsertTask");
Dim exec As Executable = package.Executables.Add("STOCK:BulkInsertTask")
La lista siguiente muestra los nombres para cada tarea que se utilizan después del moniker STOCK.
ActiveXScriptTask
BulkInsertTask
ExecuteProcessTask
ExecutePackageTask
Exec80PackageTask
FileSystemTask
FTPTask
MSMQTask
PipelineTask
ScriptTask
SendMailTask
SQLTask
TransferStoredProceduresTask
TransferLoginsTask
TransferErrorMessagesTask
TransferJobsTask
TransferObjectsTask
TransferDatabaseTask
WebServiceTask
WmiDataReaderTask
WmiEventWatcherTask
XMLTask
Si prefiere una sintaxis más explícita o si la tarea que desea agregar no tiene un moniker STOCK, puede agregar la tarea al ejecutable utilizando su nombre largo. Esta sintaxis requiere que también especifique el número de versión de la tarea.
Executable exec = package.Executables.Add(
"Microsoft.SqlServer.Dts.Tasks.ScriptTask.ScriptTask, " +
"Microsoft.SqlServer.ScriptTask, Version=10.0.000.0, " +
"Culture=neutral, PublicKeyToken=89845dcd8080cc91");
Dim exec As Executable = package.Executables.Add( _
"Microsoft.SqlServer.Dts.Tasks.ScriptTask.ScriptTask, " & _
"Microsoft.SqlServer.ScriptTask, Version=10.0.000.0, " & _
"Culture=neutral, PublicKeyToken=89845dcd8080cc91")
Puede obtener el nombre largo de la tarea mediante programación, sin tener que especificar la versión de la tarea, con la propiedad AssemblyQualifiedName de la clase, como se muestra en el ejemplo siguiente. En este ejemplo se requiere una referencia al ensamblado Microsoft.SqlServer.SQLTask.
using Microsoft.SqlServer.Dts.Tasks.ExecuteSQLTask;
...
Executable exec = package.Executables.Add(
typeof(Microsoft.SqlServer.Dts.Tasks.ExecuteSQLTask.ExecuteSQLTask).AssemblyQualifiedName);
Imports Microsoft.SqlServer.Dts.Tasks.ExecuteSQLTask
...
Dim exec As Executable = package.Executables.Add( _
GetType(Microsoft.SqlServer.Dts.Tasks.ExecuteSQLTask.ExecuteSQLTask).AssemblyQualifiedName)
En el ejemplo de código siguiente se muestra cómo crear una colección Executables a partir de un nuevo paquete y, a continuación, cómo agregar una tarea de sistema de archivos y una tarea de inserción masiva a la colección, con sus monikers STOCK. En este ejemplo se requiere una referencia a los ensamblados Microsoft.SqlServer.FileSystemTask y Microsoft.SqlServer.BulkInsertTask.
using System;
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SqlServer.Dts.Tasks.FileSystemTask;
using Microsoft.SqlServer.Dts.Tasks.BulkInsertTask;
namespace Microsoft.SqlServer.Dts.Samples
{
class Program
{
static void Main(string[] args)
{
Package p = new Package();
// Add a File System task to the package.
Executable exec1 = p.Executables.Add("STOCK:FileSystemTask");
TaskHost thFileSystemTask = exec1 as TaskHost;
// Add a Bulk Insert task to the package.
Executable exec2 = p.Executables.Add("STOCK:BulkInsertTask");
TaskHost thBulkInsertTask = exec2 as TaskHost;
// Iterate through the package Executables collection.
Executables pExecs = p.Executables;
foreach (Executable pExec in pExecs)
{
TaskHost taskHost = (TaskHost)pExec;
Console.WriteLine("Type {0}", taskHost.InnerObject.ToString());
}
Console.Read();
}
}
}
Imports Microsoft.SqlServer.Dts.Runtime
Imports Microsoft.SqlServer.Dts.Tasks.FileSystemTask
Imports Microsoft.SqlServer.Dts.Tasks.BulkInsertTask
Module Module1
Sub Main()
Dim p As Package = New Package()
' Add a File System task to the package.
Dim exec1 As Executable = p.Executables.Add("STOCK:FileSystemTask")
Dim thFileSystemTask As TaskHost = CType(exec1, TaskHost)
' Add a Bulk Insert task to the package.
Dim exec2 As Executable = p.Executables.Add("STOCK:BulkInsertTask")
Dim thBulkInsertTask As TaskHost = CType(exec2, TaskHost)
' Iterate through the package Executables collection.
Dim pExecs As Executables = p.Executables
Dim pExec As Executable
For Each pExec In pExecs
Dim taskHost As TaskHost = CType(pExec, TaskHost)
Console.WriteLine("Type {0}", taskHost.InnerObject.ToString())
Next
Console.Read()
End Sub
End Module
Salida del ejemplo:
Type Microsoft.SqlServer.Dts.Tasks.FileSystemTask.FileSystemTask
Type Microsoft.SqlServer.Dts.Tasks.BulkInsertTask.BulkInsertTask
Contenedor TaskHost
La clase TaskHost es un contenedor que no aparece en la interfaz gráfica de usuario, pero es muy importante en la programación. Esta clase es un contenedor para cada tarea. Las tareas que se agregan al paquete mediante el método Add como un objeto Executable se pueden convertir como un objeto TaskHost. Cuando una tarea se convierte como TaskHost, puede utilizar propiedades y métodos adicionales en la tarea. Además, se puede tener acceso a la propia tarea mediante la propiedad InnerObject de TaskHost. Según sus necesidades, puede mantener la tarea como un objeto TaskHost para utilizar sus propiedades a través de la colección Properties. La ventaja de utilizar Properties es que puede escribir código más genérico. Si necesita código muy específico para una tarea, debe convertir la tarea a su objeto adecuado.
En el ejemplo de código siguiente se muestra cómo convertir TaskHost, thBulkInsertTask, que contiene BulkInsertTask, a un objeto BulkInsertTask.
BulkInsertTask myTask = thBulkInsertTask.InnerObject as BulkInsertTask;
Dim myTask As BulkInsertTask = CType(thBulkInsertTask.InnerObject, BulkInsertTask)
En el ejemplo de código siguiente se muestra cómo convertir el ejecutable a TaskHost y, a continuación, cómo utilizar la propiedad InnerObject para determinar qué tipo de ejecutable contiene el host.
using System;
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SqlServer.Dts.Tasks.FileSystemTask;
using Microsoft.SqlServer.Dts.Tasks.BulkInsertTask;
namespace Microsoft.SqlServer.Dts.Samples
{
class Program
{
static void Main(string[] args)
{
Package p = new Package();
// Add a File System task to the package.
Executable exec1 = p.Executables.Add("STOCK:FileSystemTask");
TaskHost thFileSystemTask1 = exec1 as TaskHost;
// Add a Bulk Insert task to the package.
Executable exec2 = p.Executables.Add("STOCK:BulkInsertTask");
TaskHost thFileSystemTask2 = exec2 as TaskHost;
// Iterate through the package Executables collection.
Executables pExecs = p.Executables;
foreach (Executable pExec in pExecs)
{
TaskHost taskHost = (TaskHost)pExec;
if (taskHost.InnerObject is Microsoft.SqlServer.Dts.Tasks.FileSystemTask.FileSystemTask)
{
// Do work with FileSystemTask here.
Console.WriteLine("Found task of type {0}", taskHost.InnerObject.ToString());
}
else if (taskHost.InnerObject is Microsoft.SqlServer.Dts.Tasks.BulkInsertTask.BulkInsertTask)
{
// Do work with BulkInsertTask here.
Console.WriteLine("Found task of type {0}", taskHost.InnerObject.ToString());
}
// Add additional statements to check InnerObject, if desired.
}
Console.Read();
}
}
}
Imports Microsoft.SqlServer.Dts.Runtime
Imports Microsoft.SqlServer.Dts.Tasks.FileSystemTask
Imports Microsoft.SqlServer.Dts.Tasks.BulkInsertTask
Module Module1
Sub Main()
Dim p As Package = New Package()
' Add a File System task to the package.
Dim exec1 As Executable = p.Executables.Add("STOCK:FileSystemTask")
Dim thFileSystemTask1 As TaskHost = CType(exec1, TaskHost)
' Add a Bulk Insert task to the package.
Dim exec2 As Executable = p.Executables.Add("STOCK:BulkInsertTask")
Dim thFileSystemTask2 As TaskHost = CType(exec2, TaskHost)
' Iterate through the package Executables collection.
Dim pExecs As Executables = p.Executables
Dim pExec As Executable
For Each pExec In pExecs
Dim taskHost As TaskHost = CType(pExec, TaskHost)
If TypeOf taskHost.InnerObject Is Microsoft.SqlServer.Dts.Tasks.FileSystemTask.FileSystemTask Then
' Do work with FileSystemTask here.
Console.WriteLine("Found task of type {0}", taskHost.InnerObject.ToString())
ElseIf TypeOf taskHost.InnerObject Is Microsoft.SqlServer.Dts.Tasks.BulkInsertTask.BulkInsertTask Then
' Do work with BulkInsertTask here.
Console.WriteLine("Found task of type {0}", taskHost.InnerObject.ToString())
End If
' Add additional statements to check InnerObject, if desired.
Next
Console.Read()
End Sub
End Module
Salida del ejemplo:
Found task of type Microsoft.SqlServer.Dts.Tasks.FileSystemTask.FileSystemTask
Found task of type Microsoft.SqlServer.Dts.Tasks.BulkInsertTask.BulkInsertTask
La instrucción Executables.Add devuelve un ejecutable que se convierte a un objeto TaskHost a partir del objeto Executable recién creado.
Para establecer propiedades o llamar a métodos en el nuevo objeto, existen dos opciones:
Utilice la colección Properties de TaskHost. Por ejemplo, para obtener una propiedad del objeto, utilice th.Properties["propertyname"].GetValue(th)). Para establecer una propiedad, utilice th.Properties["propertyname"].SetValue(th, <value>);.
Convierta InnerObject de TaskHost a la clase de tarea. Por ejemplo, para convertir la tarea Inserción masiva a BulkInsertTask después de agregarla a un paquete como Executable y posteriormente convertirla a TaskHost, utilice BulkInsertTask myTask = th.InnerObject as BulkInsertTask;.
La utilización de la clase TaskHost en código, en lugar de convertir a la clase específica de la tarea presenta las siguientes ventajas:
El proveedor TaskHostProperties no requiere una referencia al ensamblado en el código.
Puede codificar rutinas genéricas que funcionan en cualquier tarea, ya que no es necesario conocer el nombre de la tarea en tiempo de compilación. Estas rutinas genéricas incluyen métodos donde se pasa el nombre de la tarea al método; el código del método funciona en todas las tareas. Éste es un método adecuado para escribir código de prueba.
La conversión de TaskHost a la clase específica de la tarea presenta las siguientes ventajas:
El proyecto de Visual Studio proporciona finalización de instrucciones (IntelliSense).
El código se puede ejecutar con más rapidez.
Los objetos específicos de la tarea habilitan el enlace anticipado y las optimizaciones resultantes. Para obtener más información el enlace anticipado y el enlace en tiempo de ejecución, vea el tema correspondiente en Conceptos del lenguaje Visual Basic.
En el ejemplo de código siguiente se amplía el concepto de reutilización de código de la tarea. En lugar de convertir las tareas a sus equivalentes de clase específicos, el ejemplo de código muestra cómo convertir el ejecutable a TaskHost y, a continuación, cómo utilizar Properties para escribir código genérico para todas las tareas.
using System;
using Microsoft.SqlServer.Dts.Runtime;
namespace Microsoft.SqlServer.Dts.Samples
{
class Program
{
static void Main(string[] args)
{
Package package = new Package();
string[] tasks = { "STOCK:SQLTask", "STOCK:ScriptTask",
"STOCK:ExecuteProcessTask", "STOCK:PipelineTask",
"STOCK:FTPTask", "STOCK:SendMailTask", "STOCK:MSMQTask" };
foreach (string s in tasks)
{
TaskHost taskhost = package.Executables.Add(s) as TaskHost;
DtsProperties props = taskhost.Properties;
Console.WriteLine("Enumerating properties on " + taskhost.Name);
Console.WriteLine(" TaskHost.InnerObject is " + taskhost.InnerObject.ToString());
Console.WriteLine();
foreach (DtsProperty prop in props)
{
Console.WriteLine("Properties for " + prop.Name);
Console.WriteLine("Name : " + prop.Name);
Console.WriteLine("Type : " + prop.Type.ToString());
Console.WriteLine("Readable : " + prop.Get.ToString());
Console.WriteLine("Writable : " + prop.Set.ToString());
Console.WriteLine();
}
}
Console.Read();
}
}
}
Imports Microsoft.SqlServer.Dts.Runtime
Module Module1
Sub Main()
Dim package As Package = New Package()
Dim tasks() As String = New String() {"STOCK:SQLTask", "STOCK:ScriptTask", _
"STOCK:ExecuteProcessTask", "STOCK:PipelineTask", _
"STOCK:FTPTask", "STOCK:SendMailTask", "STOCK:MSMQTask"}
For Each s As String In tasks
Dim taskhost As TaskHost = CType(package.Executables.Add(s), TaskHost)
Dim props As DtsProperties = taskhost.Properties
Console.WriteLine("Enumerating properties on " & taskhost.Name)
Console.WriteLine(" TaskHost.InnerObject is " & taskhost.InnerObject.ToString())
Console.WriteLine()
For Each prop As DtsProperty In props
Console.WriteLine("Properties for " + prop.Name)
Console.WriteLine(" Name : " + prop.Name)
Console.WriteLine(" Type : " + prop.Type.ToString())
Console.WriteLine(" Readable : " + prop.Get.ToString())
Console.WriteLine(" Writable : " + prop.Set.ToString())
Console.WriteLine()
Next
Next
Console.Read()
End Sub
End Module
Recursos externos
Entrada del blog, sobre EzAPI, actualizado para SQL Server 2012, en blogs.msdn.com.
|