Tech Talk – C# : SAP ConnectorI think this is a really interesting article which I found in the Stack Overflow website. Credit goes to the Stack Overflow and the members.

An example using vs2010 and SAP .NET Connector 3.0
Requirements:

  • Visual Studio .NET 2010 (the free c# Express edition is fine)
  • SAP .NET Connector 3.0 (you can usually obtain it from your client for the project at hand)

Installation
Identify the correct version for your platform. You might have something along the following:

Xybernetics Inc

For a Windows 7 64-bit installation, we’ll use sapnco30dotnet40P_12-20007348.zip.
Expand the archive, and start the .msi installation file.

Xybernetics SAP Connector using C#

Follow the installation procedure, leaving all default options as they are.

Referencing
Identify the correct version for your platform. You might have something along the following:
Open Visual Studio and create a new project (or open your own). In the Solution Explorer panel, usually to your right, right-click on References and choose Add Reference:

Xybernetics SAP Connector using C#

Then, select the Browse tab, navigate to the SAP Connector installation folder, and select both sapnco.dll and sapnco_utils.dll :

Xybernetics SAP Connector using C#

Now that you’ve correctly referenced the SAP .NET Connector in your Visual Studio project, you can write code for it.

Connecting
Start by creating a destination configuration class (replace the connection parameters with the ones you’re given by your client):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SAP.Middleware.Connector; // your sap connector

namespace WindowsFormsSapApplication1
{
    public class ECCDestinationConfig : IDestinationConfiguration
    {

        public bool ChangeEventsSupported()
        {
            return false;
        }

        public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;

        public RfcConfigParameters GetParameters(string destinationName)
        {

            RfcConfigParameters parms = new RfcConfigParameters();

            if (destinationName.Equals("mySAPdestination"))
            {
                parms.Add(RfcConfigParameters.AppServerHost, "sapnode.mycompany.net");
                parms.Add(RfcConfigParameters.SystemNumber, "21");
                parms.Add(RfcConfigParameters.SystemID, "CF1");
                parms.Add(RfcConfigParameters.User, "mySAPuser");
                parms.Add(RfcConfigParameters.Password, "mySAPpassword");
                parms.Add(RfcConfigParameters.Client, "100");
                parms.Add(RfcConfigParameters.Language, "EN");
                parms.Add(RfcConfigParameters.PoolSize, "5");
            }
            return parms;

        }
    }
}

Then, connect to SAP and call a function. Suppose that you want to retrieve the list of companies, using the BAPI_COMPANYCODE_GETLIST SAP function:

public void GetCompanies() {
	ECCDestinationConfig cfg = new ECCDestinationConfig();
	RfcDestinationManager.RegisterDestinationConfiguration(cfg);
	RfcDestination dest = RfcDestinationManager.GetDestination("mySAPdestination");
	RfcRepository repo = dest.Repository;
	IRfcFunction testfn = repo.CreateFunction("BAPI_COMPANYCODE_GETLIST");
	testfn.Invoke(dest);
	var companyCodeList = testfn.GetTable("COMPANYCODE_LIST");
	// companyCodeList now contains a table with companies and codes
}

Making life easier
In the above example, the GetTable function returns a SAP table which you may like, or not. There’s a handy extension that transforms that table in a familiar .NET DataTable, as follows:

public static class IRfcTableExtentions
{
    /// Converts SAP table to .NET DataTable table
    /// The SAP table to convert.
    public static DataTable ToDataTable(this IRfcTable sapTable, string name)
    {
        DataTable adoTable = new DataTable(name);
        //... Create ADO.Net table.
        for (int liElement = 0; liElement < sapTable.ElementCount; liElement++)
        {
            RfcElementMetadata metadata = sapTable.GetElementMetadata(liElement);
            adoTable.Columns.Add(metadata.Name, GetDataType(metadata.DataType));
        }

        //Transfer rows from SAP Table ADO.Net table.
        foreach (IRfcStructure row in sapTable)
        {
            DataRow ldr = adoTable.NewRow();
            for (int liElement = 0; liElement < sapTable.ElementCount; liElement++)
            {
                RfcElementMetadata metadata = sapTable.GetElementMetadata(liElement);

                switch (metadata.DataType)
                {
                    case RfcDataType.DATE:
                        ldr[metadata.Name] = row.GetString(metadata.Name).Substring(0, 4) + row.GetString(metadata.Name).Substring(5, 2) + row.GetString(metadata.Name).Substring(8, 2);
                        break;
                    case RfcDataType.BCD:
                        ldr[metadata.Name] = row.GetDecimal(metadata.Name);
                        break;
                    case RfcDataType.CHAR:
                        ldr[metadata.Name] = row.GetString(metadata.Name);
                        break;
                    case RfcDataType.STRING:
                        ldr[metadata.Name] = row.GetString(metadata.Name);
                        break;
                    case RfcDataType.INT2:
                        ldr[metadata.Name] = row.GetInt(metadata.Name);
                        break;
                    case RfcDataType.INT4:
                        ldr[metadata.Name] = row.GetInt(metadata.Name);
                        break;
                    case RfcDataType.FLOAT:
                        ldr[metadata.Name] = row.GetDouble(metadata.Name);
                        break;
                    default:
                        ldr[metadata.Name] = row.GetString(metadata.Name);
                        break;
                }
            }
            adoTable.Rows.Add(ldr);
        }
        return adoTable;
    }

    private static Type GetDataType(RfcDataType rfcDataType)
    {
        switch (rfcDataType)
        {
            case RfcDataType.DATE:
                return typeof(string);
            case RfcDataType.CHAR:
                return typeof(string);
            case RfcDataType.STRING:
                return typeof(string);
            case RfcDataType.BCD:
                return typeof(decimal);
            case RfcDataType.INT2:
                return typeof(int);
            case RfcDataType.INT4:
                return typeof(int);
            case RfcDataType.FLOAT:
                return typeof(double);
            default:
                return typeof(string);
        }
    }
}

Notes

  • While this example is based on Visual Studio 2010, other Visual Studio editions should run just fine.
  • It appears that SAP function names in the Connector should be always UPPERCASE.
  • If you get the SAP Connector architecture wrong, e.g. you install the 64bit version and then try to compile for 32-bit x86, you will get an error like: “Could not load file or assembly ‘sapnco, Version=3.0.0.42, Culture=neutral, PublicKeyToken=50436dca5c7f7d23’ or one of its dependencies. An attempt was made to load a program with an incorrect format.” This is normal; just install the correct version.

Reference