C#使用sapnoc类库SAPRFC接口调用

 

  1. 使用NuGet引用sapnoc程序包来进行RFC接口的连接,类库框架为framework,暂不支持.net Core框架,会提示冲突。

     

 

 

   

  1. 编写SapRfcHelper帮助类供接口的连接调用

using SAP.Middleware.Connector;

using System;

using System.Collections.Generic;

using System.Data;

using System.Linq;

using System.Runtime.CompilerServices;

using System.Text;

using System.Threading.Tasks;

 

namespace SAPRFC

{

    /// <summary>

    /// Rfc连接Sap的帮助类

    /// </summary>

    public class SapRfcHelper

    {

        #region 单例模式

        private SapRfcHelper()

        {

 

        }

 

        /// <summary>

        /// 创建锁对象

        /// </summary>

        private static readonly object LockObj = new object();

 

        /// <summary>

        /// 创建帮助类实例

        /// </summary>

        private static SapRfcHelper _instance;

 

        private static SapRfcHelper Instance

        {

            get

            {

                lock (LockObj)

                {

                    if (_instance == null)

                    {

                        _instance = new SapRfcHelper();

                    }

                    return _instance;

                }

            }

        }

        #endregion

 

        #region RFC操作客户端

        private RfcDestination _sapRfcDestination;

 

        public RfcDestination SapRfcDestination

        {

            get

            {

                if( _sapRfcDestination == null)

                {

                    _sapRfcDestination = RfcDestinationManager.GetDestination("saprfc");

                    

                }

                return _sapRfcDestination;

            }

 

            private set

            {

                _sapRfcDestination = value;

            }

        }

        #endregion

 

        #region 方法

        /// <summary>

        /// 获取RFC操作对象

        /// </summary>

        /// <returns></returns>

        public RfcRepository GetRfcRepository()

        {

            return SapRfcDestination.Repository;

        }

 

        /// <summary>

        /// RFCTable转化为DataTable

        /// </summary>

        /// <param name="table"></param>

        /// <returns></returns>

        public DataTable ToDataTable(IRfcTable table)

        {

            DataTable rtnDt = new DataTable();

 

            for( var i = 0;i <= table.ElementCount - 1; i++)

            {

                RfcElementMetadata metadata = table.GetElementMetadata(i);

                rtnDt.Columns.Add(metadata.Name);

            }

 

            foreach(IRfcStructure row in table)

            {

                DataRow dr = rtnDt.NewRow();

                for( var i = 0; i <= table.ElementCount - 1; i++)

                {

                    RfcElementMetadata metadata = table.GetElementMetadata(i);

                    dr[metadata.Name] = row.GetString(metadata.Name);

                }

                rtnDt.Rows.Add(dr);

            }

 

            return rtnDt;

        }

 

        /// <summary>

        /// 调用RFC接口方法

        /// </summary>

        /// <param name="FuncName">方法名称</param>

        /// <param name="InPut">输入参数</param>

        /// <param name="OutPut">输出参数</param>

        /// <param name="tablename">输出表</param>

        /// <returns></returns>

        public RetObj CallRFCFunc(string FuncName,List<InputParams>InPut,List<cloumn>OutPut,string tablename = "")

        {

            RetObj retObj = new RetObj();

            DataTable rtnDt = new DataTable();

 

            try

            {

                var rfcRepository = GetRfcRepository();

                var rfcFunction = rfcRepository.CreateFunction(FuncName);

 

                #region 输入参数管理

                InPut.ForEach(item =>

                {

                    switch(item.inputType)

                    {

                        case 1:

                            item.cloumns.ForEach(sub =>

                            {

                                rfcFunction.SetValue(sub.name, sub.value);

                            });

                            break;

                        case 2:

                            var table = rfcFunction.GetTable(item.tableName);

                            if(item.rows.Count == 0)

                            {

                                table.Insert();

                                item.cloumns.ForEach(sub =>

                                {

                                    table.CurrentRow.SetValue(sub.name, sub.value);

                                });

                            }

                            else

                            {

                                item.rows.ForEach(row =>

                                {

                                    table.Insert();

                                    row.ForEach(sub =>

                                    {

                                        table.CurrentRow.SetValue(sub.name, sub.value);

                                    });

                                });

                            }

                            break;

                    }

                });

                #endregion

 

                rfcFunction.SetParameterActive(0, true);

                rfcFunction.Invoke(_sapRfcDestination);

 

                OutPut.ForEach(item =>

                {

                    item.value = rfcFunction.GetValue(item.name).ToString();

                });

                retObj.retval = OutPut;

 

                if(!string.IsNullOrWhiteSpace(tablename))

                {

                    var rfcTable = rfcFunction.GetTable(tablename);

                    retObj.rettab = ToDataTable(rfcTable);

                }

 

            }

            catch (Exception ex)

            {

                //日志记录或抛出异常信息

            }

 

            return retObj;

        }

 

 

        #endregion

    }

}

 

封装的SapRfcParams参数类

using System;

using System.Collections.Generic;

using System.Data;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace SAPRFC

{

    public class cloumn

    {

        /// <summary>

        /// 参数名称

        /// </summary>

        public string name {  get; set; }

        /// <summary>

        /// 参数值

        /// </summary>

        public string value { get; set; }

    }

 

    public class InputParams

    {

        /// <summary>

        /// 参数类型:0,无入参;1,键值对;2,参数表

        /// </summary>

        public int inputType { get; set; }

        /// <summary>

        /// 参数表名

        /// </summary>

        public string tableName {  get; set; }

        /// <summary>

        /// 入参字段

        /// </summary>

        public List<cloumn> cloumns { get; set; }

        /// <summary>

        /// 入参表行

        /// </summary>

        public List<List<cloumn>> rows { get; set; }

    }

 

    public class RetObj

    {

        public List<cloumn> retval { get; set; }

        public DataTable rettab { get; set; }

    }

}

 

  1. 编写测试调用程序,实际使用调用方法一致

编写Win Form程序调用接口,主要目标平台选为64位,默认为32

 

修改连接配置文件,配置SAP接口的连接

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

    <startup>

        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />

    </startup>

<configSections>

<sectionGroup name="SAP.Middleware.Connector">

<sectionGroup name ="ClientSettings">

<section name="DestinationConfiguration" type="SAP.Middleware.Connector.RfcDestinationConfiguration,sapnco"/>

</sectionGroup>

</sectionGroup>

</configSections>

<SAP.Middleware.Connector>

<ClientSettings>

<DestinationConfiguration>

<destinations>

<add NAME="saprfc" USER="test" PASSWORD="123456" CLIENT="900" SYSNR="00" ASHOST="127.0.0.1" LANG="zh" SAPROUTER="" MAX_POOL_SIZE="10" IDLE_TIMEOUT="600"/>

</destinations>

</DestinationConfiguration>

</ClientSettings>

</SAP.Middleware.Connector>

<!--配置此條的目的是為了解決不同編譯版本引起的衝突。-->

<!--例如當前我們的項目使用的編譯環境是.net4.0,然後我們引用其他自行編寫的DLL使用的是.NET3.5版本,就會發生衝突。-->

<startup useLegacyV2RuntimeActivationPolicy="true">

<supportedRuntime version="4.0"/>

</startup>

</configuration>

 

调用接口的参数组装代码示例:

using SAPRFC;

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

 

namespace TestRFCWinForm

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

 

        private void button1_Click(object sender, EventArgs e)

        {

            //获取RFC接口实例

            var rfc = SapRfcHelper.Instance;

 

            #region 输入参数组装

            var input = new List<InputParams>();

            var cloumns = new List<cloumn>();

 

            cloumns.Add(new cloumn

            {

                name = "name1",

                value = "value1"

            });

 

            input.Add(new InputParams

            {

                inputType = 2,

                tableName = "table",

                cloumns = cloumns,

                rows = new List<List<cloumn>>()

            });

 

            #endregion

 

            #region 输出参数组装

            var output = new List<cloumn>()

            {

                new cloumn

                {

                    name = "out",

                    value = "value"

                }

            };

            #endregion

 

            #region 调用接口,获取返回值

            var rtnObj = rfc.CallRFCFunc("funcname",input,output,"tablename");

 

            //返回键值对

            var message = rtnObj.retval.Find(x => x.name == "out").ToString();

            //返回表

            var dt = rtnObj.rettab;

            #endregion

        }

    }

}

 

posted @ 2024-02-27 10:05  江渔湖  阅读(165)  评论(0编辑  收藏  举报