Таким образом, на базе данного коннектора возможно реализовать модуль для интеграции, который может быть развернут как на 32х-битном, так и на 64х-битном web-приложении.
Так как коннектор поставляется для двух версий фреймворка .NET – 2.0 (3.0/3.5) и 4.0, то модуль для интеграции может функционировать в контексте SharePoint 2007/2010/2013 версии.
В рамках данной статьи я продемонстрирую, на примере создания консольного приложения на языке C#, способ получения информации о заказах из SAP.
Для начала необходимо создать в Visual Studio 2010 новый проект типа "Консольное приложение Windows". Я назвал проект "InvoiceDataConsole".
В новом проекте создаем класс "SAPSystemConnect", реализующий интерфейс "IDestinationConfiguration". Этот класс необходим для управления конфигурацией и подключением к SAP.
Для использования интерфейса "IDestinationConfiguration" нам потребуется добавить референсы на библиотеки
sapnco.dll и
sapnco_utils.dll из папки, в которую мы производили установку пакета в предыдущем пункте.
В файле, содержащем описание класса "SAPSystemConnect" добавим namespace "SAP.Middleware.Connector". Используя класс "SAPSystemConnect", добавим реализацию методов интерфейса "IDestinationConfiguration". В листинге ниже показано, как выглядит исходный код класса "SAPSystemConnect" и реализация методов:
using SAP.Middleware.Connector;
namespace InvoiceDataConsole
{
class SAPSystemConnect : IDestinationConfiguration
{
public bool ChangeEventsSupported()
{
return false;
}
public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
public RfcConfigParameters GetParameters(string destination)
{
//Получаем параметры подключения в порядке: _sysNum,_Host,_User,_Pass,_sysID,_mandt
string[] pars = destination.Split(',');
string _sysNum = pars[0];
string _Host = pars[1];
string _User = pars[2];
string _Pass = pars[3];
string _sysID = pars[4];
string _mandt = pars[5];
//Инициализация объекта, содержащего параметры подключения
RfcConfigParameters _params = new RfcConfigParameters();
_params.Add(RfcConfigParameters.AppServerHost, _Host);
_params.Add(RfcConfigParameters.SystemNumber, _sysNum);
_params.Add(RfcConfigParameters.SystemID, _sysID);
_params.Add(RfcConfigParameters.Client, _mandt);
_params.Add(RfcConfigParameters.Language, "RU");
_params.Add(RfcConfigParameters.User, _User);
_params.Add(RfcConfigParameters.Password, _Pass);
_params.Add(RfcConfigParameters.PoolSize, "5");
_params.Add(RfcConfigParameters.IdleTimeout, "5000");
_params.Add(RfcConfigParameters.Name, "MYSAPCONNECT");
return _params;
}
}
}
Листинг 1 - Исходный текст файла SAPSystemConnect.cs
Хочу обратить ваше внимание на код метода "GetParameters()": сначала мы получаем набор параметров для подключения и сохраняем их в строковый массив. Далее для удобства присваиваем переменным с "говорящими" названиями соответствующие значения параметров. После этого создаем новый объект "_params" типа "RfcConfigParameters". Этот класс необходим для управления параметрами подключения к SAP.
Для взаимодействия с SAP необходимо иметь представление о свойствах вызываемого RFC-модуля, таких как:
- имя вызываемого RFC-модуля
- имена входных и выходных параметров
- имена получаемых структур и таблиц, а также названия их полей
Для удобства я создал отдельный класс с константами "Constants", в котором содержится вся информация для вызова RFC-модуля. Данный класс приведен в листинге ниже.
namespace InvoiceDataConsole
{
public static class Constants
{
public static class InvoiceTable
{
//Имя вызываемого модуля
public const string Z_RFC_GET_INV = "Z_RFC_GET_INV";
//Входной параметр для вызова модуля
public const string INV_CODE = "INV_CODE01";
//Имя основного объекта "счет-фактура"
public const string INV_MAIN = "INV_MAIN01";
//Выходные параметры объекта "счет-фактура"
public const string INV_NAME = "INV_NAME01";
public const string INV_ADDR = "INV_ADDR01";
public const string INV_INN = "INV_INN01";
public const string INV_KPP = "INV_KPP01";
//Таблица с реквизитами банковских счетов для оплаты
public static class INV_BANK_LIST
{
//Имя таблицы
public const string _FULLTABLENAME = "INV_BANK01";
//Поля таблицы
public const string INV_BRNCH = "INV_BRNCH01";
public const string INV_BVTY = "INV_BVTY01";
public const string INV_BANK = "INV_BANK01";
}
}
}
}
Листинг 2 - Исходный текст файла Constants.cs
Установка подключения
Для установки подключения к SAP необходимо использовать интерфейс "RFCDestination". Добавим в проект новый класс "Connection", в котором реализуем наш собственный метод "InitConnection()", принимающий в качестве входного параметра строку для подключения к SAP. Данный метод возвращает объект типа "RFCDestination". В листинге ниже видно, что в теле метода "InitConnection()" происходит инициализация нового экземпляра класса "SAPSystemConnect" - sapCfg. Далее этот объект используется для передачи параметров подключения в метод "GetDestination()" класса "RfcDestinationManager", который в свою очередь создает и инициализирует объект типа "RFCDestination".
using SAP.Middleware.Connector;
using System;
namespace InvoiceDataConsole
{
public class Connection
{
public static RfcDestination InitConnection(string connection)
{
try
{
SAPSystemConnect sapCfg = new SAPSystemConnect();
RfcDestination rfcDest = RfcDestinationManager.GetDestination(sapCfg.GetParameters(connection));
return rfcDest;
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
return null;
}
}
}
}
Листинг 3 - Исходный текст файла Connection.cs
Написание собственного класса для хранения и отображения информации по счету-фактуре
Создадим класс "InvoiceData", в котором будет реализовано получение и вывод информации по счету-фактуре.
В самом классе укажем строковые свойства, в которые будет сохранятся информация только по заданному счету:
- INV_NAME - название организации
- INV_ADDR - адрес организации
- INV_INN - ИНН организации
- INV_KPP - КПП организации
Далее определим список "BankData", в который будет сохранятся таблица с реквизитами банковских счетов для оплаты - объектов типа "table_INV_BANK".
Данный объект содержит свойства:
- INV_BRNCH - номер отделения банка
- INV_BCODE - номенклатурный номер банка
- INV_BANK - наименование отделения банка
Для запроса данных из SAP напишем реализацию метода "GetDetails()".
Вначале необходимо инициализировать обращение к репозиторию в SAP - rfcDest.Repository.
После этого необходимо создать и инициализировать объект "rfc" типа "IRfcFunction", используя метод "CreateFunction()", которому нужно передать название RFC-модуля. Используя метод "SetValue()" мы передаем входной параметр (INV_CODE - номер счета) в вызываемый модуль. Сам же вызов осуществляется в методе "Invoke()".
Далее нам необходимо получить основную информацию по счету-фактуре.
Для этого создаем и инициализируем объект "mainStruct" типа "IRfcStructure", используя метод "GetStructure()", которому нужно передать имя основного объекта "счет-фактура" (INV_MAIN). После этого, используя метод "GetValue()" и названия выходных параметров объекта "счет-фактура", заполняем свойства основного класса "InvoiceData".
Чтобы получить информацию по реквизитам банковских счетов для оплаты счета-фактуры, выполним следующие действия.
Создадим и инициализируем объект "invTable" типа "IRfcTable", используя метод "GetTable()", которому нужно передать имя таблицы с реквизитами (_FULLTABLENAME). Далее, перебирая в цикле строки в таблице "invTable", заполняем список "BankData" реквизитами банковских счетов.
Для отображения информации по "счету-фактуре" и банковским реквизитам в консоли, напишем реализацию метода "Display()", который (как я надеюсь) в комментариях не нуждается.
Исходный текст класса "InvoiceData" приведен в листинге ниже.
using SAP.Middleware.Connector;
using System.Collections.Generic;
using NAME = InvoiceDataConsole.Constants.InvoiceTable;
using System;
namespace InvoiceDataConsole
{
public class InvoiceData
{
public string INV_NAME { get; set; }
public string INV_ADDR { get; set; }
public string INV_INN { get; set; }
public string INV_KPP { get; set; }
public class table_INV_BANK
{
public string INV_BRNCH { get; set; }
public string INV_BCODE { get; set; }
public string INV_BANK { get; set; }
}
private List <table_INV_BANK> _bankData = new List <table_INV_BANK>();
public List <table_INV_BANK> BankData
{
get { return _bankData; }
set { _bankData = value; }
}
public void GetDetails(RfcDestination rfcDest, string code)
{
RfcRepository repo = rfcDest.Repository;
IRfcFunction rfc = repo.CreateFunction(NAME.Z_RFC_GET_INV);
rfc.SetValue(NAME.INV_CODE, code);
rfc.Invoke(rfcDest);
IRfcStructure mainStruct = rfc.GetStructure(NAME.INV_MAIN);
this.INV_ADDR = mainStruct.GetValue(NAME.INV_ADDR).ToString();
this.INV_INN = mainStruct.GetValue(NAME.INV_INN).ToString();
this.INV_KPP = mainStruct.GetValue(NAME.INV_KPP).ToString();
this.INV_NAME = mainStruct.GetValue(NAME.INV_NAME).ToString();
IRfcTable invTable = rfc.GetTable(NAME.INV_BANK_LIST._FULLTABLENAME);
if (invTable.RowCount > 0)
{
for (int cuIndex = 0; cuIndex < invTable.RowCount; cuIndex++)
{
table_INV_BANK data = new table_INV_BANK();
invTable.CurrentIndex = cuIndex;
data.INV_BANK = invTable.CurrentRow.GetValue(NAME.INV_BANK_LIST.INV_BANK).ToString();
data.INV_BRNCH = invTable.CurrentRow.GetValue(NAME.INV_BANK_LIST.INV_BRNCH).ToString();
data.INV_BCODE = invTable.CurrentRow.GetValue(NAME.INV_BANK_LIST.INV_BVTY).ToString();
this.BankData.Add(data);
}
}
}
public void Display()
{
Console.WriteLine(); Console.WriteLine();
Console.WriteLine("Display invoice data");
Console.WriteLine("INV_NAME: " + this.INV_NAME);
Console.WriteLine("INV_ADDR: " + this.INV_ADDR);
Console.WriteLine("INV_INN: " + this.INV_INN);
Console.WriteLine("INV_KPP: " + this.INV_KPP);
Console.WriteLine();
Console.WriteLine("Display banking details");
foreach (var item in this.BankData)
{
Console.WriteLine("INV_BANK: " + item.INV_BANK);
Console.WriteLine("INV_BRNCH: " + item.INV_BRNCH);
Console.WriteLine("INV_BCODE: " + item.INV_BCODE);
Console.WriteLine();
}
}
}
}
Листинг 4 - Исходный текст файла InvoiceData.cs
Собираем все вместе
Структура итогового проекта изображена на рисунке ниже.
Нам осталось написать код главной программы "Main".
Вначале задаем строку для подключения к SAP, в которой указываем необходимые значения параметров через запятую.
Далее инициализируем назначение удаленного вызова "rfcDest", используя метод "InitConnection()" из нашего класса. Для проверки доступности подключения к SAP используется метод "Ping()".
После проверки создаем новый экземпляр "invoice" нашего класса "InvoiceData".
С помощью метода "GetDetails()" получаем информацию из SAP по счету-фактуре с номером "1234" и заполняем данными наш объект "invoice".
Для вывода информации в консоль вызываем метод Display().
Коннектор предоставляет несколько специальных классов-исключений, которые перехватываются с помощью стандартного try{}catch{}.
Листинг файла с главной программой приведен ниже.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SAP.Middleware.Connector;
using SAP.Middleware;
namespace InvoiceDataConsole
{
class Program
{
static void Main(string[] args)
{
//Задаем строку подключения с параметрами: sysNum,Host,User,Pass,sysID,mandt
string ConnectionString = @"10,http://saphost,User,Password,TST,800";
//Инициализация подключения
RfcDestination rfcDest = Connection.InitConnection(ConnectionString);
//Открываем скоуп для удаленного вызова
RfcSessionManager.BeginContext(rfcDest);
try
{
//Проверка подключения к SAP
Console.Write("Testing connection to SAP: ");
rfcDest.Ping();
Console.Write("CONNECTION_SUCCESSFUL!");
InvoiceData invoice = new InvoiceData();
invoice.GetDetails(rfcDest, "1234");
invoice.Display();
}
catch (RfcCommunicationException ex)
{
//Ошибка подключения
ShowError(ex);
}
catch (RfcLogonException ex)
{
//Ошибка аутентификации учетной записи, под которой производится подключение
ShowError(ex);
}
catch (RfcAbapRuntimeException ex)
{
//Ошибка выполнения ABAP
ShowError(ex);
}
catch (RfcAbapBaseException ex)
{
//Ошибка ABAP
ShowError(ex);
}
catch (Exception ex)
{
//Общая ошибка
RfcSessionManager.EndContext(rfcDest);
ShowError(ex);
}
finally
{
//Закрываем скоуп
RfcSessionManager.EndContext(rfcDest);
Console.WriteLine("Press key...");
Console.ReadKey();
}
}
private static void ShowError(Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
}
Листинг 5 - Исходный текст файла Program.cs
Результат работы программы изображен на рисунке ниже.
Подведем итоги
Как вы успели заметить, на второй взгляд, во взаимодействии с SAP через коннектор нет ничего архисложного.
Настройка и инициализация подключения, описание классов для получения и обработки данных из нужных структур в SAP - все это доступно благодаря .NET коннектору!
Надеюсь, что этот пост поможет вам начать работу с коннектором.
Если у вас появятся предложения по улучшению данного материала, то оставьте свой комментарий ниже.
Ссылки по теме
1. Используемые в статье материалы
2. Дополнительные материалы с портала SAP