Этот пошаговый пример предназначен для тех, кто может наткнуться на этот вопрос. В этом примере используются сервер Windows Server 2008 R2 и SSIS 2008 R2 . Несмотря на то, что в примере используется SSIS 2008 R2 , используемая логика применима и к SSIS 2005 . Спасибо @Kev
за FTPWebRequest код.
Создание пакета служб SSIS ( Шаги по созданию пакета служб SSIS ). В начале я назвал пакет в формате YYYYMMDD_hhmm, за которым следует SO , обозначающий переполнение стека, за которым следует SO, идентификатор вопроса и, наконец, описание. Я не говорю, что вы должны назвать свою посылку вот так. Это для меня, чтобы легко отослать это позже. Обратите внимание, что у меня также есть два источника данных, а именно Adventure Works и Practice DB . Я буду использовать источник данных Adventure Works , который указывает на базу данных AdventureWorks , загруженную с по этой ссылке . См. Скриншот # 1 внизу ответа.
В базе данных AdventureWorks создайте хранимую процедуру с именем dbo.GetCurrency , используя приведенный ниже скрипт.
CREATE PROCEDURE [dbo].[GetCurrency]
AS
BEGIN
SET NOCOUNT ON;
SELECT
TOP 10 CurrencyCode
, Name
, ModifiedDate
FROM Sales.Currency
ORDER BY CurrencyCode
END
GO
В разделе диспетчера подключений пакета щелкните правой кнопкой мыши и выберите Новое подключение из источника данных . В диалоговом окне Выбор источника данных выберите Adventure Works и нажмите OK . Теперь вы должны увидеть источник данных Adventure Works в разделе «Менеджеры соединений». Смотрите скриншот # 2 , # 3 и # 4 .
В пакете создайте следующие переменные. Смотрите скриншот # 5 .
ColumnDelimiter : эта переменная имеет тип String. Это будет использоваться для разделения данных столбца при его записи в файл. В этом примере мы будем использовать запятую (,), а код написан для обработки только отображаемых символов. Для неотображаемых символов, таких как tab (\ t), вам может потребоваться соответственно изменить код, используемый в этом примере.
FileName : эта переменная имеет тип String. Он будет содержать имя файла. В этом примере я назвал файл как Currencies.csv, потому что я собираюсь экспортировать список названий валют.
FTPPassword : эта переменная имеет тип String. Это будет содержать пароль к FTP-сайту. В идеале пакет должен быть зашифрован, чтобы скрыть конфиденциальную информацию.
FTPRemotePath : эта переменная имеет тип String. Он будет содержать путь к папке FTP, в которую должен быть загружен файл. Например, если полный URI FTP равен ftp: //myFTPSite.com/ssis/samples/uploads, то RemotePath будет /ssis/samples/uploads.
FTPServerName : эта переменная имеет тип String. Он будет содержать корневой URI FTP-сайта. Например, если полный URI FTP равен ftp: //myFTPSite.com/ssis/samples/uploads, то FTPServerName будет содержать ftp: //myFTPSite.com. Вы можете комбинировать FTPRemotePath с этой переменной и иметь одну переменную. Это на ваше усмотрение.
FTPUserName : эта переменная имеет тип String. Он будет содержать имя пользователя, которое будет использоваться для подключения к FTP-сайту.
ListOfCurrencies : Эта переменная имеет тип Object. Он будет содержать набор результатов из хранимой процедуры, и он будет зациклен в задаче сценария.
ShowHeader : эта переменная имеет тип Boolean. Это будет содержать значения true / false. Значение True указывает, что первая строка в файле будет содержать имена столбцов, а значение False указывает, что первая строка не будет содержать имен столбцов.
SQLGetData : эта переменная имеет тип String. Это будет содержать оператор выполнения хранимой процедуры. В этом примере используется значение EXEC dbo.GetCurrency
На вкладке Поток управления пакета поместите Выполнить задачу SQL и назовите ее Получить данные . Дважды щелкните на задаче «Выполнение SQL», чтобы вызвать редактор «Выполнить задачу SQL» . В разделе General редактора задач Execute SQL установите ResultSet на Full result set
, Connection на Adventure Works
, SQLSourceType до Variable
и SourceVariable до User::SQLGetData
. В разделе «Набор результатов» нажмите кнопку «Добавить». Установите для имени результата значение 0
, это указывает на индекс и переменную на User::ListOfCurrencies
. Вывод хранимой процедуры будет сохранен в этой переменной объекта. Нажмите OK . Смотрите скриншот # 6 и # 7 .
На вкладке пакета Поток управления поместите задачу сценария ниже задачи «Выполнение SQL» и назовите ее Сохранить на FTP . Дважды щелкните «Задача сценария», чтобы вызвать редактор задач сценария . В разделе «Сценарий» нажмите кнопку Edit Script…
. Смотрите скриншот # 8 . Это вызовет редактор инструментов Visual Studio Tools for Applications (VSTA). Замените код в классе ScriptMain
в редакторе на код, приведенный ниже. Также убедитесь, что вы добавили операторы using в пространства имен System.Data.OleDb
, System.IO
, System.Net
, System.Text
. См. Снимок экрана # 9 , который выделяет изменения кода. Закройте редактор VSTA и нажмите Ok, чтобы закрыть редактор задач Script. Код сценария берет объектную переменную ListOfCurrencies и сохраняет ее в DataTable с помощью OleDbDataAdapter, потому что мы используем соединение OleDb. Затем код проходит по каждой строке, и если для переменной ShowHeader задано значение true, код будет включать имена столбцов в первой строке, записанной в файл. Результат сохраняется в переменной stringbuilder. После того как переменная построителя строк заполнена всеми данными, код создает объект FTPWebRequest и подключается к Uri FTP путем объединения переменных FTPServerName, FTPRemotePath и FileName с использованием учетных данных, указанных в переменных FTPUserName и FTPPassword. Затем полное содержимое переменной строителя строки записывается в файл. Метод WriteRowData создается для обхода столбцов и предоставления имен столбцов или информации о данных на основе переданных параметров.
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
using System.Data.OleDb;
using System.IO;
using System.Net;
using System.Text;
namespace ST_7033c2fc30234dae8086558a88a897dd.csproj
{
[System.AddIn.AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
#region VSTA generated code
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
#endregion
public void Main()
{
Variables varCollection = null;
Dts.VariableDispenser.LockForRead("User::ColumnDelimiter");
Dts.VariableDispenser.LockForRead("User::FileName");
Dts.VariableDispenser.LockForRead("User::FTPPassword");
Dts.VariableDispenser.LockForRead("User::FTPRemotePath");
Dts.VariableDispenser.LockForRead("User::FTPServerName");
Dts.VariableDispenser.LockForRead("User::FTPUserName");
Dts.VariableDispenser.LockForRead("User::ListOfCurrencies");
Dts.VariableDispenser.LockForRead("User::ShowHeader");
Dts.VariableDispenser.GetVariables(ref varCollection);
OleDbDataAdapter dataAdapter = new OleDbDataAdapter();
DataTable currencies = new DataTable();
dataAdapter.Fill(currencies, varCollection["User::ListOfCurrencies"].Value);
bool showHeader = Convert.ToBoolean(varCollection["User::ShowHeader"].Value);
int rowCounter = 0;
string columnDelimiter = varCollection["User::ColumnDelimiter"].Value.ToString();
StringBuilder sb = new StringBuilder();
foreach (DataRow row in currencies.Rows)
{
rowCounter++;
if (rowCounter == 1 && showHeader)
{
WriteRowData(currencies, row, columnDelimiter, true, ref sb);
}
WriteRowData(currencies, row, columnDelimiter, false, ref sb);
}
string ftpUri = string.Concat(varCollection["User::FTPServerName"].Value,
varCollection["User::FTPRemotePath"].Value,
varCollection["User::FileName"].Value);
FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpUri);
ftp.Method = WebRequestMethods.Ftp.UploadFile;
string ftpUserName = varCollection["User::FTPUserName"].Value.ToString();
string ftpPassword = varCollection["User::FTPPassword"].Value.ToString();
ftp.Credentials = new System.Net.NetworkCredential(ftpUserName, ftpPassword);
using (StreamWriter sw = new StreamWriter(ftp.GetRequestStream()))
{
sw.WriteLine(sb.ToString());
sw.Flush();
}
Dts.TaskResult = (int)ScriptResults.Success;
}
public void WriteRowData(DataTable currencies, DataRow row, string columnDelimiter, bool isHeader, ref StringBuilder sb)
{
int counter = 0;
foreach (DataColumn column in currencies.Columns)
{
counter++;
if (isHeader)
{
sb.Append(column.ColumnName);
}
else
{
sb.Append(row[column].ToString());
}
if (counter != currencies.Columns.Count)
{
sb.Append(columnDelimiter);
}
}
sb.Append(System.Environment.NewLine);
}
}
}
После настройки задач поток управления пакета должен выглядеть так, как показано на скриншоте # 10 .
Снимок экрана # 11 показывает выходные данные оператора выполнения хранимой процедуры EXEC dbo.GetCurrency.
Выполнить пакет. Снимок экрана # 12 показывает успешное выполнение пакета.
Используя надстройку FireFTP , доступную в браузере FireFox , я вошел на сайт FTP и убедился, что файл успешно загружен на сайт FTP. Смотрите скриншот # 13 .
Изучение содержимого путем открытия файла в Notepad ++ показывает, что оно совпадает с выводом хранимой процедуры. Смотрите скриншот # 14 .
Таким образом, в примере показано, как записывать результаты из базы данных на веб-сайт FTP без использования временных / локальных файлов.
Надеюсь, это кому-нибудь поможет.
Скриншоты:
# 1 : Solution_Explorer
# 2 : New_Connection_From_Data_Source
# 3 : Select_Data_Source
# 4 : Connection_Managers
# 5 : переменные
# 6 : Execute_SQL_Task_Editor_General
# 7 : Execute_SQL_Task_Editor_Result_Set
# 8 : Script_Task_Editor
# 9 : Script_Task_VSTA_Code
# 10 : Control_Flow_Tab
# 11 : Query_Results
# 12 : Package_Execution_Successful
# 13 : File_In_FTP
# 14 : File_Contents