SAP .Net 調用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; }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章