SAP .Net 调用RFC通用方法

本文介绍如何使用C#通过SAP NetConnector 3.0库调用SAP系统的RFC功能,包括环境搭建、类库使用、连接配置、RFC函数调用及结果处理。

来源
C# SAP .Net Connector 3.0連接RFC示例

必备环境:

1,类库sapnco.dll、sapnco_utils.dll。可以通过官方下载安装取得,也可以直接从网上只下载这两个类库,还能直接从NuGet获取:Install-Package SAPDotNetConnector3 -Version 0.3.0

2,Microsoft Visual C++ 2010 Redistributable Package,简称Microsoft Visual C++ 2010 。下载链接,可从控制面板查看已安装程序确认有没安装。Windows更新中可能已包含了Microsoft Visual C++ 2010,但不在已安装程序中显示。

步骤1:SAP定义RFC

步骤2:C#实现

a):调用SAP RFC封装类:

namespace RFCLib
{
    //C#代码创建Sap连接对象的类SapConnection
    public class SapConnection : IDestinationConfiguration
    {
        RfcConfigParameters IDestinationConfiguration.GetParameters(string destinationName) //或 public  RfcConfigParameters GetParameters(string destinationName)
        {
            SAPClient sapClient;
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(SAPClient));
            string sapClientSettingPath = System.AppDomain.CurrentDomain.BaseDirectory+ "SAPClientSetting.config";
            using (System.IO.FileStream fileStream = new System.IO.FileStream(sapClientSettingPath, System.IO.FileMode.Open))
            {
                sapClient = (SAPClient)serializer.Deserialize(fileStream);
            }
            return GetParameters(destinationName, sapClient);            
        }

        public RfcConfigParameters GetParameters(string destinationName, SAPClient sapInfo)
        {
            RfcConfigParameters conf = new RfcConfigParameters();
            if (destinationName == "NSP")//给连接SAP的对象命个名
            {
                //先添加必填参数       
                conf.Add(RfcConfigParameters.SystemNumber, sapInfo.SystemNumber);
                //conf.Add(RfcConfigParameters.SystemID, "");
                conf.Add(RfcConfigParameters.User, sapInfo.User);
                conf.Add(RfcConfigParameters.Password, sapInfo.Password);
                conf.Add(RfcConfigParameters.Client, sapInfo.Client);
                conf.Add(RfcConfigParameters.Language, sapInfo.Language);


                //添加可选参数(普通登陆参数)
                if (!string.IsNullOrEmpty(sapInfo.ApplicationServer))
                    conf.Add(RfcConfigParameters.AppServerHost, sapInfo.ApplicationServer);

                if (!string.IsNullOrEmpty(sapInfo.AppServerService))
                    conf.Add(RfcConfigParameters.AppServerService, sapInfo.AppServerService);

                //添加可选参数(服务器组参数)
                if (!string.IsNullOrEmpty(sapInfo.MessageServerHost))
                    conf.Add(RfcConfigParameters.MessageServerHost, sapInfo.MessageServerHost);

                if (!string.IsNullOrEmpty(sapInfo.MessageServerService))
                    conf.Add(RfcConfigParameters.MessageServerService, sapInfo.MessageServerService);

                if (!string.IsNullOrEmpty(sapInfo.LogonGroup))
                    conf.Add(RfcConfigParameters.LogonGroup, sapInfo.LogonGroup);

                if (!string.IsNullOrEmpty(sapInfo.SystemID))
                    conf.Add(RfcConfigParameters.SystemID, sapInfo.SystemID);
            }
            return conf;
        }
        public bool ChangeEventsSupported()
        {
            return true;
        }
        public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
    }

    //SAP连接参数类
    public class SAPClient
    {

        public string ApplicationServer { get; set; }   //应用服务器IP地址,如 10.88.88.88
        public string AppServerService { get; set; }
        public string Client { get; set; }              //sap客户端 如 100
        public string Language { get; set; }            //语言,如 ZH 或 EN
        public string LogonGroup { get; set; }          //登录组名
        public string MessageServerHost { get; set; }   //消息服务器IP地址 
        public string MessageServerService { get; set; }
        public string Password { get; set; }            //登录密码
        public string SystemID { get; set; }            //系统标识
        public string SystemNumber { get; set; }        //实例号,如 00
        public string User { get; set; }                //登录账号
    }


    //自定义的调用RFC的类
    public class NcoQueryRFC
    {
        //创建Sap连接对象的类SapConnection的实例global_dest,单例模式
        private static RfcDestination global_dest;
        public static RfcDestination SapConnInfo()
        {
            if (global_dest == null)
            {
                //SapConnection类定义见代码末
                SapConnection con= new SapConnection(); 
                RfcDestinationManager.RegisterDestinationConfiguration(con);
            }

            //这里定义
            global_dest = RfcDestinationManager.GetDestination("NSP");
            return global_dest;
        }


        //查询RFC的方法 
        //public static IRfcFunction ExcuteAndGetSAPFuntion(string funtionName,List<Dictionary<string,object>> functionparamsList)
        /// <summary>
        /// 调用RFC并获取SAP函数调用结果
        /// </summary>
        /// <param name="funtionName">函数名称</param>
        /// <param name="functionparamsList">函数所需参数</param>
        /// <returns>RFC调用结果</returns>
        static IRfcFunction ExcuteAndGetSAPFuntion(string funtionName, List<Dictionary<string, object>> functionparamsList)
        {
            RfcDestination dest = NcoQueryRFC.SapConnInfo();
            RfcRepository rfcrep = dest.Repository;
            IRfcFunction myfun = rfcrep.CreateFunction(funtionName); //RFC的名称
            foreach (Dictionary<string,Object> functionparams in functionparamsList)
            {
                foreach (var item in functionparams)
                {
                    myfun.SetValue(item.Key, item.Value);
                }
            }
            myfun.Invoke(dest);//调用
            return myfun;//直接返回function,取到的结果由调用者提取。
        }

        //查询RFC导出
        public static Dictionary<string, object> GetRFCExport(string funtionName, List<Dictionary<string, object>> functionparamsList, List<string> exportParams)
        {
            Dictionary<string, object> exports = new Dictionary<string, object>();
            IRfcFunction myfun = ExcuteAndGetSAPFuntion(funtionName,functionparamsList); //RFC的名称

            foreach (string exportParam in exportParams)
            {
                exports.Add(exportParam,myfun.GetValue(exportParam));
            }
            return exports;
        }
        
        /// <summary>
        /// 调用RFC,获取返回的table
        /// </summary>
        /// <param name="funtionName">函数名</param>
        /// <param name="functionparamsList">函数参数列表</param>
        /// <param name="tableName">RFC中定义的返回table的名称</param>
        /// <returns></returns>
        public static IRfcTable GetRFCTable(string funtionName, List<Dictionary<string, object>> functionparamsList, string tableName)
        {
            Dictionary<string, object> exports = new Dictionary<string, object>();
            IRfcFunction myfun = ExcuteAndGetSAPFuntion(funtionName, functionparamsList); //RFC的名称
            IRfcTable rfcTable = myfun.GetTable(tableName);
            return rfcTable;
        }
    }
}

b):RFC返回Table转.Net平台DataTable对象。

        /// <summary>
        /// 将RFC返回的Table转换为.Net平台的DataTable对象
        /// </summary>
        /// <param name="rfcTable">RFC返回Table</param>
        /// <returns>转换后的.Net平台DataTable对象</returns>
        DataTable GetRFCData(IRfcTable rfcTable)
        {
            DataTable sourceTable = new DataTable();
            string columnName;
            //新增列
            for (int i = 0; i < rfcTable.Metadata.LineType.FieldCount; i++)
            {
                columnName = rfcTable.Metadata[i].Name;
                sourceTable.Columns.Add(columnName);
            }
            DataRow row;
            //新增行
            foreach (SAP.Middleware.Connector.IRfcStructure item in rfcTable)
            {
                row = sourceTable.NewRow();
                string cellValue;
                for (int i = 0; i < rfcTable.Metadata.LineType.FieldCount; i++)
                {
                    columnName = rfcTable.Metadata[i].Name;
                    cellValue = item.GetString(columnName); 
                    //NUM类型,去除前导0
                    if (rfcTable.Metadata[i].DataType == RfcDataType.NUM )
                    {
                        cellValue = Convert.ToInt32(item.GetString(columnName)).ToString();
                    }
                    row[columnName] = cellValue;
                }
                sourceTable.Rows.Add(row);
            }
            return sourceTable;
        }

c):C#通过封装类库调用RFC

/// <summary>
/// 从SAP根据料号及类别获取SAP图文档类别、编号、版本、名称
/// </summary>
/// <param name="part">料号</param>
/// <param name="sapDoctype">SAP类别代号</param>
///// <param name="code">返回结果状态码:0成功 1失败</param>
///// <param name="msg">返回结果描述</param>
/// <param name="result">返回结果</param>
[WebMethod(Description = "从SAP根据料号及类别获取图文档类别、编号、版本、名称")]
//public void GetPLMCADD_SAP(string part, string sapDoctype, ref string code,ref string msg,  ref object result)
public string GetPLMCADD_SAP(string part, string sapDoctype)
{

    #region 初始返回对象与参数检验
    SAPServiceResult sAPServiceResult = new SAPServiceResult()
            {
                Code = "1",
                Message = "未处理!",
                Data = null
            };
    if (string.IsNullOrEmpty(part) || string.IsNullOrEmpty(sapDoctype))
            {
                sAPServiceResult.Message = "缺少参数";
                return Newtonsoft.Json.JsonConvert.SerializeObject(sAPServiceResult, Newtonsoft.Json.Formatting.Indented);
            }
    else if (!RFCLib.RFC.SAPDocTypes.Split(',').Contains(sapDoctype))
    {
        sAPServiceResult.Message = $"类别{sapDoctype}不存在";
        return Newtonsoft.Json.JsonConvert.SerializeObject(sAPServiceResult, Newtonsoft.Json.Formatting.Indented);
    }
    #endregion

    List<Dictionary<string, object>> paramsList = new List<Dictionary<string, object>>();
    Dictionary<string, object> keyValuePairs2 = new Dictionary<string, object>() { { "IM_MATNR", part } };
    paramsList.Add(keyValuePairs2);
    //1,通过料号获取SAP图文档类别、编号、版本、名称
    string rfcTableName = RFCLib.RFC.sapRfcs.Where(x => x.Name == "ZPLM_MAT_LINK_DIRS_GET_MES").Take(1).Select(x => x.Table.Name).FirstOrDefault();
    IRfcTable rfcTable = RFCLib.NcoQueryRFC.GetRFCTable("ZPLM_MAT_LINK_DIRS_GET_MES", paramsList, rfcTableName);
    DataTable ZPLM_MAT_LINK_DIRS_GET_TableData = GetRFCData(rfcTable);
    DataRow row1 = ZPLM_MAT_LINK_DIRS_GET_TableData.AsEnumerable().Where(x => x["DOKAR"].ToString() == sapDoctype.Trim()).OrderByDescending(x => x["DOKVR"]).FirstOrDefault();
    object[] rowData = row1.ItemArray;//先将结果保存起来,否则Rows.Clear()后,row1会被清空。
    ZPLM_MAT_LINK_DIRS_GET_TableData.Rows.Clear();
    ZPLM_MAT_LINK_DIRS_GET_TableData.Rows.Add(rowData);
    sAPServiceResult.Code = "0";
    sAPServiceResult.Message = "ok";
    sAPServiceResult.Data = ZPLM_MAT_LINK_DIRS_GET_TableData;
    string jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(sAPServiceResult, Newtonsoft.Json.Formatting.Indented);
    return jsonStr;
}

/// <summary>
/// SAPService接口返回封装对象
/// </summary>
class SAPServiceResult
{
    /// <summary>
    /// 状态码:0执行成功,其他执行失败
    /// </summary>
    public string Code { get; set; }
    /// <summary>
    /// 说明
    /// </summary>
    public string Message { get; set; }
    /// <summary>
    /// 执行结果
    /// </summary>
    public object Data { get; set; }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值