SapCo2
SAP Connector for .Net5
Install / Use
/learn @metalsimyaci/SapCo2README
SapCo2 (SAP Connector Core)
We tried to design SAPCO2 as a library for data processing over SAP in the simplest and fastest way. We focused on quick use, simplifying it as much as possible.
Referenced by SapNwRfc and NwRfcNet projects that were previously developed during the development phase. I recommend that you take a look at these two projects before examining the project. Especially the Wrapper parts have emerged by combining the common aspects of the two projects.
supportted .Net Core, Net 5 ve .Net Frameworks.
I would like to thank Mahmut KOLTUK for his contributions at many points in the new architectural structure.
Requiretment
Our library needs .dll files developed with C ++ in SAP NetWeaver RFC Library 7.50 SDK. For the installation of the relevant SDK package and more: You can refer to the official page of: sparkles: SAP.
After obtaining the relevant SKD (requires an SAP licensed account from you);
- Extract your zip file to a directory of your own and show the lib directory in the files you extract to the environment variable
PATH(Windows),LD_LIBRARY_PATH(Linux),DYLD_LIBRARY_PATH(MacOS) according to your operating system. - or directly copy the contents of the lib folder to your output directory.
To use the SDK package in the Windows operating system, you must install the 64-bit version of Visual C ++ 2013 redistributable package.
Instalization
PackageManager
Install-Package SapCo2
Or DotNet
dotnet add package SapCo2
or Package Referance
<PackageReference Include="SapCo2" Version="1.2.0.1" />
Note: Has dependencies Microsoft.Extensions.DependencyInjection and Microsoft.Extensions.Options.
Usage
You can access all the examples described in the document with the projects under the Samples directory.
To use it, we add it with .AddSapCo2 on Dependency injection. It needs connection information in the add process.
Connection
To assign the connection information as a string
var connectionString = "Name=ALIAS1;AppServerHost=HOST_NAME; SystemNumber=00; User=USER; Password=PASSWORD; Client=CLIENT_CODE; Language=EN; PoolSize=100; Trace=0;";
or multiple in Appsettings.json
{
"SapCo2": {
"DefaultServer": "ALIAS1",
"Connections": [
{
"Alias": "ALIAS1",
"ConnectionPooling": {
"Enabled": false,
"PoolSize": 8,
"IdleTimeout": "00:00:30",
"IdleDetectionInterval": "00:00:01"
},
"ConnectionString": "Name=ALIAS1;User=USER;Password=PASSWORD;Client=CLIENT_CODE;SystemId:xxx;Language=EN;AppServerHost=HOST_NAME;SystemNumber=00;MaxPoolSize:100;PoolSize=50;IdleTimeout:600;Trace=0;",
"ConnectionOptions": {}
},
{
"Alias": "ALIAS2",
"ConnectionPooling": {
"Enabled": false,
"PoolSize": 8,
"IdleTimeout": "00:00:30",
"IdleDetectionInterval": "00:00:01"
},
"ConnectionString": "",
"ConnectionOptions": {
"Name": "ALIAS2",
"User": "USER",
"Password": "PASSWORD",
"Client": "CLIENT_CODE",
"SystemId": "xxx",
"Language": "TR",
"AppServerHost": "HOST_NAME",
"SystemNumber": "00",
"MaxPoolSize": "100",
"PoolSize": "50",
"IdleTimeout": "600",
"Trace": "0"
}
}
]
}
}
in appsetting.json;
- You can assign connection information with
ConnectionStringorConnectionOptions. - You can define multiple connections as ALIAS1 or ALIAS2.
- Set a Default connection, it is sufficient to specify the
Aliasin the connection definitions in theDefaultServerpart.
Dependency Injection
Startup.cs veya Program.cs veya vb.
IConfiguration configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json", optional: true)
.AddEnvironmentVariables()
.Build();
Dependencyinjection ile IServceProvider içerisinde .AddSapCo2 fonksiyonuna IConfiguration bilgisi atayarak kullanabiliriz.
IConfiguration with Appsettings
var serviceCollection = new ServiceCollection();
serviceCollection.AddOptions<IConfiguration>();
serviceCollection.Configure<IOptions<IConfiguration>>(configuration);
serviceCollection.AddSapCo2(s=>s.ReadFromConfiguration(configuration));
var serviceProvider = serviceCollection.BuildServiceProvider();
Custom Configuration
var serviceCollection = new ServiceCollection()
.AddSapCo2(s =>
{
s.DefaultServer = "LIVE";
s.RfcServers = new List<RfcServer>()
{
new RfcServer()
{
Alias = "LIVE",
ConnectionString =
"Name=LIVE;User=USER;Password=PASSWORD;Client=CLIENT_CODE;SystemId:xxx;Language=EN;AppServerHost=HOST_NAME;SystemNumber=00;MaxPoolSize:100;PoolSize=50;IdleTimeout:600;Trace=0;",
ConnectionPooling = new RfcConnectionPoolingOption() {Enabled = true, PoolSize = 10}
}
};
});
var serviceProvider = serviceCollection.BuildServiceProvider();
IRFCClient Implementation
SAPCO2 can be used in 3 ways. Table, Bapi and RFC. In addition to these, a feature has been added where we will receive Meta Data for RFC and BAPI.
RFC
The most basic of these is RFC (Remote Functon Call). In other stages, it is actually a customized and simplified form of it. You can perform all operations using only RFC.
It will be sufficient if you create your input and output objects before the function call and pass them as parameters.
As an example, I used the recipe function CS_BOM_EXPL_MAT_V2_RFC for RFC. associated with it
I create the BomInputParameter class for the parameters I want to give as a condition, and the BomOutputParameter class for the values I want to get back.
I create these classes by selecting the fields I want to use from import and export, Table objects related to SAP SE37.
By marking my classes that I created with the RfcEntityPropertAttribute attribute, we specify the corresponding name on the SAP side. If we want, we can also provide an explanation of what happened.
I exclude properties that are not on the SAP side but are in my class with the RfcEntityIgnorePropertyAttribute attribute.
public sealed class BomInputParameter: IRfcInput
{
[RfcEntityProperty("AUMGB")]
public string Aumgb { get; set; }
[RfcEntityProperty("CAPID")]
public string Capid { get; set; }
[RfcEntityProperty("DATUV")]
public DateTime Datuv { get; set; }
[RfcEntityProperty("EMENG")]
public string Emeng { get; set; }
[RfcEntityProperty("MKTLS")]
public string Mktls { get; set; }
[RfcEntityProperty("MEHRS")]
public string Mehrs { get; set; }
[RfcEntityProperty("STPST")]
public string Stpst { get; set; }
[RfcEntityProperty("SVWVO")]
public string Svwvo { get; set; }
[RfcEntityProperty("WERKS")]
public string Werks { get; set; }
[RfcEntityProperty("VRSVO")]
public string Vrsvo { get; set; }
[RfcEntityProperty("STLAN")]
public string Stlan { get; set; }
[RfcEntityProperty("STLAL")]
public string Stlal { get; set; }
[RfcEntityProperty("MTNRV")]
public string Mtnrv { get; set; }
}
</details>
As a condition, I define the production site code with plantcode and the material for which I want to get a recipe as a variable with materialCode.
var inputParameter = new BomInputParameter {
Aumgb = "0",
Capid = "PP01",
Datuv = DateTime.Now,
Emeng = "1",
Mktls = "x",
Mehrs = "x",
Stpst = "0",
Svwvo = "x",
Werks = plantCode,
Vrsvo = "x",
Stlal = "1",
Stlan = "1",
Mtnrv = materialCode
};
For the return values, we reference the structor and the table in our BomOutputParameter class. We show the tables as [] array.
public sealed class BomOutputParameter: IRfcOutput
{
[RfcEntityProperty("STB")]
public Stb[] StbData { get; set; }
[RfcEntityProperty("TOPMAT")]
public Topmat Topmat { get; set; }
}
<details>
<summary>Table Stb Class</summary>
public sealed class Stb
{
[RfcEntityProperty("STUFE", Description = "Seviye")]
public int Level { get; set; }
[RfcEntityProperty("OJTXB", Description = "Nesne kısa metni (bileşen grubu)")]
public string Name { get; set; }
[RfcEntityPrope
