Программное добавление задач
Задачи могут быть добавлены в среде выполнения к объектам следующих типов.
Эти классы рассматриваются как контейнеры, причем все они наследуют свойство Executables. Контейнеры могут содержать коллекцию задач, представляющих собой исполняемые объекты, которые обрабатываются средой выполнения во время выполнения контейнера. Порядок выполнения объектов в коллекции определяется любым набором PrecedenceConstraint для каждой задачи в контейнерах. Элементы управления очередностью включают ветвление выполнения в зависимости от успеха, неудачи или завершения любого объекта Executable в коллекции.
Каждый контейнер имеет коллекцию Executables, которая содержит отдельные объекты Executable. Каждая исполняемая задача наследует и реализует методы Executable..::..Execute и Executable..::..Validate. Эти два метода вызываются средой выполнения для обработки каждого объекта Executable.
Чтобы добавить задачу к пакету, необходим контейнер с существующей коллекцией Executables. В большинстве случаев задачей, добавляемой к коллекции, является пакет. Чтобы добавить новый исполняемый файл задачи в коллекцию для этого контейнера, необходимо вызвать метод Executables..::..Add. Этот метод имеет единственный параметр — строку, которая содержит специальное имя CLSID, PROGID, STOCK или свойство TaskInfo..::..CreationName добавляемой задачи.
Имена задач
Задачу можно указать по имени или идентификатору, но специальное имя STOCK представляет собой параметр, используемый чаще всего в методе Executables..::..Add. Чтобы добавить задачу к исполняемому файлу, обозначенному специальным именем STOCK, используйте следующий синтаксис:
Executable exec = package.Executables.Add("STOCK:BulkInsertTask");
Dim exec As Executable = package.Executables.Add("STOCK:BulkInsertTask")
В следующем списке для каждой задачи показаны имена, которые используются после специального имени STOCK.
ActiveXScriptTask
BulkInsertTask
ExecuteProcessTask
ExecutePackageTask
Exec80PackageTask
FileSystemTask
FTPTask
MSMQTask
PipelineTask
ScriptTask
SendMailTask
SQLTask
TransferStoredProceduresTask
TransferLoginsTask
TransferErrorMessagesTask
TransferJobsTask
TransferObjectsTask
TransferDatabaseTask
WebServiceTask
WmiDataReaderTask
WmiEventWatcherTask
XMLTask
Если предпочтительным является более явный синтаксис или если задача, которую требуется добавить, не имеет специального имени STOCK, то можно добавить задачу к исполняемому файлу, используя ее длинное имя. Этот синтаксис требует, чтобы был также указан номер версии задачи.
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")
Можно получить длинное имя для задачи программным путем без обязательного указания версии задачи с помощью свойства AssemblyQualifiedName класса, как показано в следующем примере. В этом примере необходима ссылка на сборку 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)
В следующем примере кода показано, как создать коллекцию Executables из нового пакета, а затем добавить задачи «Файловая система» и «Массовая вставка» в коллекцию с использованием их специальных имен STOCK. В этом примере необходимы ссылки на сборки Microsoft.SqlServer.BulkInsertTask и Microsoft.SqlServer.FileSystemTask.
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
Вывод образца:
Тип Microsoft.SqlServer.Dts.Tasks.FileSystemTask.FileSystemTask
Тип Microsoft.SqlServer.Dts.Tasks.BulkInsertTask.BulkInsertTask
Контейнер TaskHost
Класс TaskHost представляет собой контейнер, который не появляется в графическом пользовательском интерфейсе, но очень важен в программировании. Этот класс является оболочкой для каждой задачи. Задачи, добавляемые к пакету с помощью метода Add как объекты Executable, могут быть приведены как объекты TaskHost. Если задача приведена как TaskHost, появляется возможность использовать в задаче дополнительные свойства и методы. Кроме того, можно получить доступ к самой задаче с помощью свойства InnerObject объекта TaskHost. В зависимости от конкретных потребностей, может быть решено оставить задачу в качестве объекта TaskHost, чтобы можно было использовать свойства задачи с помощью коллекции Properties. Преимущество использования коллекции Properties состоит в том, что может быть написан более общий код. Если для задачи требуется весьма конкретный код, необходимо привести задачу к соответствующему ей объекту.
В следующем примере кода показано, как привести объект TaskHost (thBulkInsertTask), который содержит задачу BulkInsertTask, к объекту BulkInsertTask.
BulkInsertTask myTask = thBulkInsertTask.InnerObject as BulkInsertTask;
Dim myTask As BulkInsertTask = CType(thBulkInsertTask.InnerObject, BulkInsertTask)
В следующем примере кода показано, как привести исполняемый файл к объекту TaskHost, а затем с помощью свойства InnerObject определить, какого типа исполняемый файл содержится на этом узле.
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
Вывод образца:
Найдена задача типа Microsoft.SqlServer.Dts.Tasks.FileSystemTask.FileSystemTask.
Найдена задача типа Microsoft.SqlServer.Dts.Tasks.BulkInsertTask.BulkInsertTask.
Инструкция Executables..::..Add возвращает исполняемый файл, который приведен к объекту TaskHost, из вновь созданного объекта Executable.
Чтобы задать свойства или вызвать методы нового объекта, можно воспользоваться одним из двух способов.
Применить коллекцию Properties объекта TaskHost. Например, для получения свойства объекта применить инструкцию th.Properties["propertyname"].GetValue(th)). Чтобы задать свойство, использовать инструкцию th.Properties["propertyname"].SetValue(th, <value>);.
Привести свойство InnerObject объекта TaskHost к классу задачи. Например, чтобы привести задачу «Массовая вставка» к задаче BulkInsertTask после ее добавления в пакет в качестве Executable и последующего приведения к TaskHost, можно использовать оператор BulkInsertTask myTask = th.InnerObject as BulkInsertTask;.
Использование в коде класса TaskHost вместо приведения к классу, зависящему от задачи, предоставляет следующие преимущества.
Для поставщика TaskHostProperties не требуется ссылка на сборку в коде.
Можно разрабатывать код общих подпрограмм, способных работать в любой задаче, поскольку нет необходимости знать имя задачи во время компиляции. Такие общие подпрограммы включают методы, в которых имя задачи передается методу, а код метода работает во всех задачах. Это удобный способ создания тестового кода.
Приведение от класса TaskHost к классу, зависящему от задачи, позволяет достичь следующих преимуществ.
Проект разрабатывается в среде Visual Studio, поэтому обеспечивается возможность автоматического завершения инструкций (с помощью технологии IntelliSense).
Код может работать быстрее.
Объекты, зависящие от задачи, обеспечивают применение раннего связывания и завершающую оптимизацию. Дополнительные сведения о раннем и позднем связывании см. в подразделе «Раннее и позднее связывание» в разделе «Основные понятия языка Visual Basic».
В следующем примере кода раскрывается понятие повторного использования кода задачи. Вместо приведения задач к конкретным эквивалентным им классам в этом примере кода показано, как привести исполняемый файл к объекту TaskHost, а затем воспользоваться коллекцией Properties для написания общего кода для всех задач.
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
|